Compare commits

..

187 Commits

Author SHA1 Message Date
Benjamin Eberlei b7a15316a0 Release 2.0.7 2011-08-17 21:47:50 +00:00
Benjamin Eberlei 2b878fc15d Bump dependency DBAL to 2.0.7 2011-08-17 21:46:43 +00:00
Benjamin Eberlei 4fea26c833 Fix: YamlDriver does not support orphanRemoval 2011-08-17 21:23:13 +02:00
Benjamin Eberlei bf3ae5f2cf Merge branch 'DDC-1302' into 2.0.x 2011-07-31 11:36:02 +02:00
Benjamin Eberlei 2836d14c31 DDC-1302 - Fix bug in XmlDriver not handling orphan removal 2011-07-31 11:35:50 +02:00
Benjamin Eberlei a342c87a32 Merge branch 'DDC-1276' into 2.0.x 2011-07-26 22:18:21 +02:00
Benjamin Eberlei 192eedc6a7 DDC-1276 - Fix bug where merge managed and new entitiy share the same collection that is cascaded, cleared during the process and then empty afterwards. 2011-07-26 22:17:13 +02:00
Benjamin Eberlei ed78cdb937 Merge remote-tracking branch 'origin/2.0.x' into 2.0.x 2011-07-12 22:52:35 +02:00
Benjamin Eberlei 793c383aa2 Merge branch 'DDC-1240' into 2.0.x 2011-07-12 22:52:18 +02:00
Benjamin Eberlei 7595b021cc DDC-1240 - Fix optimistic lock exception loosing the message 2011-07-12 22:52:09 +02:00
Benjamin Eberlei f1bcb3cb80 Merge branch 'DDC-1257' into 2.0.x 2011-07-09 15:15:53 +02:00
Benjamin Eberlei 35ea4ed1fd DDC-1257 - Fix bug where validation callbacks are added multiple times in EntityGenerator 2011-07-09 15:15:34 +02:00
Benjamin Eberlei ac8a36cda3 Merge branch 'DDC-1251' into 2.0.x 2011-07-09 14:55:12 +02:00
Benjamin Eberlei 0917ed5ced DDC-1251 - Fix bug in token parsing of EntityGenerator 2011-07-09 14:54:56 +02:00
Benjamin Eberlei 8068f34c66 DDC-1022 - Call __wakeup() with the same semantics then ClassMetadata::newInstance() does inside UnitOfWork 2011-07-09 14:34:21 +02:00
Benjamin Eberlei 91a9d4f27c Merge branch 'DDC-1230' into 2.0.x 2011-06-28 21:38:54 +02:00
Benjamin Eberlei 7c8590ea74 DDC-1230 - Fix bug where UnitOfWork does not set STATE_REMOVE when calling EntityManager#remove() on an entity 2011-06-28 21:38:44 +02:00
Benjamin Eberlei d1cea4f77c Merge branch 'DDC-1224' into 2.0.x 2011-06-26 10:12:08 +02:00
Benjamin Eberlei ae958e73d1 DDC-1224 - Bugfix with temporary table ids and tables in schema (in postgresql) 2011-06-26 10:11:57 +02:00
Benjamin Eberlei 3b841883d3 Merge branch 'DDC-1211' into 2.0.x 2011-06-19 10:27:21 +02:00
Benjamin Eberlei cfe36f9a31 DDC-1211 - Fix bug with empty numeric literal 2011-06-19 10:26:36 +02:00
Benjamin Eberlei d2eea18977 Merge branch 'DDC-1189' into 2.0.x 2011-06-19 09:44:21 +02:00
Benjamin Eberlei 247887ec0e DDC-1189 - Bugfix with PersistentCollection#clear() in combination with lazy loading 2011-06-19 09:43:33 +02:00
Benjamin Eberlei 2b309a3682 Merge remote-tracking branch 'origin/2.0.x' into 2.0.x 2011-06-16 22:47:28 +02:00
Benjamin Eberlei 5ebe7ca89e Merge branch 'DDC-1172' into 2.0.x 2011-06-16 22:47:08 +02:00
Benjamin Eberlei c582b7790a DDC-1172 - Adjust patch to 2.0.x code base 2011-06-16 22:43:06 +02:00
Benjamin Eberlei a98a21b269 DDC-1172 - Handle sequence dropping in SchemaTool. 2011-06-16 22:34:56 +02:00
Benjamin Eberlei 5c9b3d0b92 Bump Dev Version to 2.0.7-DEV 2011-06-15 21:45:09 +00:00
Benjamin Eberlei 7f3bdab34c Release 2.0.6 2011-06-15 21:44:59 +00:00
Benjamin Eberlei e075ab6958 Update dependency of DBAL to 2.0.6 2011-06-15 21:43:17 +00:00
Benjamin Eberlei a1bc743568 Merge branch 'DDC-1208' into 2.0.x 2011-06-15 18:33:24 +02:00
Benjamin Eberlei 20d8ebfd43 DDC-1208 - Allow namespace separator in <discriminator-mapping /> 2011-06-15 18:33:12 +02:00
Fabien Potencier 3587f3bcb3 Update Symfony2 vendors 2011-06-15 11:44:04 +02:00
Benjamin Eberlei ec87cb779c Merge branch 'DDC-1163' into 2.0.x 2011-06-05 16:20:56 +02:00
Benjamin Eberlei ac40ce8042 DDC-1163 - Fix nasty bug with inheritance in UnitOfWork::executeUpdates() and executeRemovals() 2011-06-05 16:20:41 +02:00
Benjamin Eberlei d4302b32e1 Merge branch 'DDC-1192' into 2.0.x 2011-06-05 14:50:35 +02:00
Benjamin Eberlei 3c95b0ec35 DDC-1192 - Fix notice in XmlDriver, removed unnecessary code. 2011-06-05 14:50:25 +02:00
Benjamin Eberlei c12c6e82b6 Merge remote-tracking branch 'origin/2.0.x' into 2.0.x 2011-06-05 10:09:26 +02:00
Benjamin Eberlei 505f7bd252 Merge branch 'DDC-1193' into 2.0.x 2011-06-05 10:08:29 +02:00
Benjamin Eberlei d5459616d2 DDC-733, DDC-1193 - Proxy has only _load() in 2.0.x - Change to __load() for consinstent code. 2011-06-05 10:08:05 +02:00
Benjamin Eberlei 97d9fb7efa DDC-733, DDC-1193 - Proxy has only _load() in 2.0.x 2011-06-05 10:06:56 +02:00
Benjamin Eberlei 2da1fadaf1 DDC-1193 - Fix previous commit. 2011-06-05 10:05:25 +02:00
Benjamin Eberlei a612ca7231 DDC-1193 - Fix bug with cascade remove and proxy classes. 2011-06-05 10:05:12 +02:00
Benjamin Eberlei bd4faa6a7d DDC-733 - Add UnitOfWork::initializeObject() method. 2011-06-05 10:04:23 +02:00
Benjamin Eberlei be03811753 Merge pull request #66 from fabpot/feat-doctrine-mapping-configuration
Feat doctrine mapping configuration
2011-06-04 23:18:52 -07:00
Fabien Potencier 636fa34136 Made orm:convert-mapping command more configurable (allow to change the extension of the generated files for instance) 2011-06-05 08:03:41 +02:00
Benjamin Eberlei 016810af7f [DDC-952] Add Persister hydration performance tests. 2011-05-14 16:09:40 +02:00
Benjamin Eberlei 178fe38a39 Bump Dev Version to 2.0.6-DEV 2011-05-14 13:36:43 +00:00
Benjamin Eberlei 35a318148c Release 2.0.5 2011-05-14 13:36:31 +00:00
Benjamin Eberlei c63115efa9 Bump DBAL dependency to 2.0.5 2011-05-14 15:32:31 +02:00
Benjamin Eberlei 7cba650aff DDC-1136 - trailing character for backup files. 2011-05-14 11:58:27 +02:00
Benjamin Eberlei d9475cbfd0 Merge remote-tracking branch 'origin/2.0.x' into 2.0.x 2011-05-14 08:49:01 +02:00
Benjamin Eberlei ee1708b04a Merge branch 'DDC-1151' into 2.0.x 2011-05-14 08:48:32 +02:00
Benjamin Eberlei a8057dfe26 DDC-1151 - Slight modification necessary for 2.0.x 2011-05-14 08:46:51 +02:00
Benjamin Eberlei 60e7b8eff4 DDC-1151 - Fix missing table quotes when adding foreign keys in SchemaTool 2011-05-14 08:45:50 +02:00
Guilherme Blanco 28291f0fa7 Merge pull request #56 from stof/DDC-1146
DDC 1146
2011-05-11 15:47:20 -07:00
Christophe Coevoet eecd9afc09 [DDC-1146] Updated the Symfony2 vendors 2011-05-12 00:28:36 +02:00
Benjamin Eberlei 8f9f85da39 Merge branch 'DDC-1129' into 2.0.x 2011-05-01 11:46:16 +02:00
Benjamin Eberlei 5d7063b2e1 [DDC-1129] Fix bug in version changeset computation aswell as inline ClassMetadata::isCollectionValuedAssociation to increase performance by 2-5% 2011-05-01 11:46:00 +02:00
Benjamin Eberlei cc26080a00 Merge branch 'DDC-1091' into 2.0.x 2011-05-01 11:02:21 +02:00
Benjamin Eberlei 2b900e2c26 [DDC-1091] Fix bug with custom string functions in StringPrimary 2011-05-01 11:02:08 +02:00
Benjamin Eberlei aedda4a21d Merge branch 'DDC-1102' into 2.0.x 2011-05-01 10:02:12 +02:00
Benjamin Eberlei de6f0e4594 DDC-1102 - Typo in EntityGenerator 2011-05-01 10:02:03 +02:00
Benjamin Eberlei d1191c3f74 Merge pull request #39 from francisbesset/parent_object_not_found.
[2.0.x] Fixed an undefined index by a HydrationException
2011-04-30 15:08:10 -07:00
Guilherme Blanco bd117fc9eb Merge pull request #49 from fabpot/namespace-parsing-fix.
[DDC-1134] Entity generator: Namespace parsing fix
2011-04-30 12:49:36 -07:00
Benjamin Eberlei ac04ce4114 Merge branch 'DBAL-115' into 2.0.x 2011-04-30 17:19:31 +02:00
Benjamin Eberlei 8d39f2a36d [DBAL-115] REALLY fix issues with SchemaTool::getDropSchemaSQL(). 2011-04-30 17:19:15 +02:00
Benjamin Eberlei e86cbd65fa [DBAL-115] Bugfix in SchemaTool not quoting table names when dropping schema. 2011-04-30 17:17:34 +02:00
Benjamin Eberlei 410dd69c5b Merge branch 'DDC-1133' into 2.0.x 2011-04-30 14:24:29 +02:00
Benjamin Eberlei 222a90fc8a DDC-1133 - Ducktype AnnotationReader in AnnotationDriver 2011-04-30 14:24:20 +02:00
Benjamin Eberlei c8e2ee05d1 Merge branch 'DDC-1109' into 2.0.x 2011-04-30 12:51:30 +02:00
Benjamin Eberlei 7c9c7369fb [DDC-1109] ltrim discriminator map for convenience. 2011-04-30 12:51:10 +02:00
Benjamin Eberlei 8ec9ee82f9 Merge branch '2.0.x' of github.com:doctrine/doctrine2 into 2.0.x 2011-04-30 12:28:29 +02:00
Benjamin Eberlei 33c896c31f Merge branch 'DDC-1108' into 2.0.x 2011-04-30 12:28:14 +02:00
Benjamin Eberlei 9ee3cc98ae [DDC-1108] Fix bug with single char named input parameters in DQL lexer. 2011-04-30 12:27:55 +02:00
Benjamin Eberlei 12bde174c5 Merge branch 'DDC-1132' into 2.0.x 2011-04-30 11:23:30 +02:00
Benjamin Eberlei 7634d45a29 [DDC-1132] Fix many to many table detection. 2011-04-30 11:20:25 +02:00
Benjamin Eberlei b2873ab236 [DDC-1132] Fix many to many table detection. 2011-04-30 11:20:25 +02:00
Fabien Potencier 2978cad198 Fix namespace/class parsing in the entity generator 2011-04-30 10:42:38 +02:00
Benjamin Eberlei c49467b7fa build.xml: Cleanup .git directory in Symfony Components 2011-04-07 15:11:52 -04:00
Benjamin Eberlei 095b8fa930 Bump Dev Version to 2.0.5-DEV 2011-04-07 15:04:05 -04:00
Benjamin Eberlei 8a2b1058c3 Release 2.0.4 2011-04-07 15:03:49 -04:00
Benjamin Eberlei 2bdceefb2d Bump dependencies, Doctrine Common to 2.0.2 and DBAL to 2.0.4 2011-04-07 20:53:19 +02:00
Benjamin Eberlei 71bcdce031 Merge branch 'DDC-1040' into 2.0.x 2011-04-03 23:08:24 +02:00
Benjamin Eberlei f6a700062d [DDC-1040] Bugfix with named parameters and multiple entities passed as parameter. 2011-04-03 23:08:07 +02:00
Benjamin Eberlei fb4db2782c [DDC-1040] Add regression tests for entity as multiple named/positional parameters. 2011-04-03 23:06:47 +02:00
Benjamin Eberlei 39ec8de08b Merge branch 'DDC-1093' into 2.0.x 2011-04-03 20:29:41 +02:00
Benjamin Eberlei 7a469581e1 [DDC-1093] Fix docblock type hint 2011-04-03 20:29:32 +02:00
Benjamin Eberlei 1f8cdb77be Merge branch 'DDC-1087' into 2.0.x 2011-04-03 09:12:10 +02:00
Benjamin Eberlei af5bcc148d [DDC-1087] Add missing resolution to IS NULL in EntityRepository when passing a null value as a criteria. 2011-04-03 09:11:54 +02:00
Benjamin Eberlei 06870fd87f Merge branch 'DDC-1077' into 2.0.x 2011-03-27 21:12:24 +02:00
Benjamin Eberlei 26af92f452 [DDC-1077] Bugfix in not handling literals in Select Expressions. 2011-03-27 21:12:05 +02:00
Benjamin Eberlei 97d97a8a89 Merge branch 'DDC-1079' into 2.0.x 2011-03-27 14:06:05 +02:00
Benjamin Eberlei 3df673cb6a [DDC-1079] Bugfix for shortcut for ArithmeticExpressions in SimpleSelectExpression that lead to literals not being valid. Problem was that ScalarExpression() did not handle AggregateExpressions() at all, which is now fixed. 2011-03-27 14:05:33 +02:00
Francis Besset 85474a0c7a Fixed an undefined index by a HydrationException 2011-03-21 20:33:32 +01:00
Benjamin Eberlei 1c05831b20 Merge ModifyLimitQueryFix into 2.0.x 2011-03-20 16:06:36 -04:00
Benjamin Eberlei 26126a10cd Bump Dev Version to 2.0.4-DEV 2011-03-20 16:04:07 -04:00
Benjamin Eberlei b6c5de3ef5 Release 2.0.3 2011-03-20 16:03:54 -04:00
Benjamin Eberlei 48fe910978 Update DBAL dependency to 2.0.3 2011-03-20 16:03:11 -04:00
Benjamin Eberlei 0df6086960 Bump Version to 2.0.3-DEV 2011-03-20 15:51:51 -04:00
Benjamin Eberlei 3d406afa38 Merge branch 'DDC-992' into 2.0.x 2011-03-20 17:14:17 +01:00
Benjamin Eberlei 526f21ad3d [DDC-992] Fix criteria usage of column names clashing with field or associations by prefixing with table names or alias. 2011-03-20 17:14:04 +01:00
Benjamin Eberlei 31722cf8f6 [DDC-1053] Fix rebase/merge mistake in tests. 2011-03-20 14:10:33 +01:00
Benjamin Eberlei 758a09dfe8 Merge branch 'DDC-1053' into 2.0.x 2011-03-20 14:09:15 +01:00
Benjamin Eberlei ba00dd13b6 [DDC-1053] Fix bug with usage of identification variables in GroupByItem. 2011-03-20 14:08:57 +01:00
Benjamin Eberlei ff65aeed60 Merge branch 'DDC-1052' into 2.0.x 2011-03-20 13:08:48 +01:00
Benjamin Eberlei 3a5d70fbf3 [DDC-1052] Fix bug with versioning and inheritance 2011-03-20 13:08:16 +01:00
Benjamin Eberlei 68257a8c93 Merge branch 'DDC-1070' into 2.0.x 2011-03-20 12:23:43 +01:00
Benjamin Eberlei 3b4596691f [DDC-1070] Fix in AbstractQuery::iterate() method not respecting hydrator and parameters. 2011-03-20 12:23:21 +01:00
Benjamin Eberlei ecb409412f Bump Dev Version to 2.0.3-DEV 2011-03-05 04:12:43 -05:00
Benjamin Eberlei 91ea598eb7 Release 2.0.2 2011-03-05 04:12:35 -05:00
Benjamin Eberlei 75e42f8145 Adjust tests to changes in DBAL dependency with regard to automatic foreign key and index naming. 2011-03-05 10:08:12 +01:00
Benjamin Eberlei c6cc39ddee Remove Test for DDC-1050 which was merged in error during rebase of DDC-1041 2011-03-05 09:22:10 +01:00
Benjamin Eberlei 211fd2a69e Add symfony components deploy mechanism to build.xml 2011-03-05 08:59:54 +01:00
Benjamin Eberlei 8eef747aba Merge branch 'DDC-1034' into 2.0.x 2011-03-04 23:02:41 +01:00
Benjamin Eberlei ceb6924aae DDC-1034 - Fix bug where callbacks where registered multiple times in inheritance hierachies. 2011-03-04 23:02:18 +01:00
Benjamin Eberlei af4e836f4f Merge branch 'DDC-1056' into 2.0.x 2011-03-04 22:22:48 +01:00
Benjamin Eberlei d650ade2b1 DDC-1056 - Fixed notice in StaticPHPDriver. 2011-03-04 22:22:31 +01:00
Benjamin Eberlei 521e4880aa Merge branch 'DDC-1041' into 2.0.x 2011-03-04 21:55:48 +01:00
Benjamin Eberlei ee951a19aa [DDC-1041] You could retrieve instances of the wrong type in inheritance hierachies because the identity map aggregates them by rootEntityName. 2011-03-04 21:55:39 +01:00
Benjamin Eberlei b1a616dfa5 Remove copied Symfony Component code 2011-03-04 21:51:07 +01:00
Benjamin Eberlei 859ca72426 Merge remote branch 'origin/2.0.x' into 2.0.x 2011-02-26 12:49:48 +01:00
Benjamin Eberlei a655188e55 Merge branch 'DDC-1033' into 2.0.x 2011-02-26 12:48:53 +01:00
Benjamin Eberlei 5be16db9ec DDC-1033 - Fix cloning of not initialized proxies. 2011-02-26 12:48:39 +01:00
Benjamin Eberlei f6aca7c6ef Merge branch 'DDC-1026' into 2.0.x 2011-02-26 00:41:03 +01:00
Benjamin Eberlei 4271706cab DDC-1026 - Fix Result Cache Seperate chaining implementation that was wrong since DDC-892 was applied. 2011-02-26 00:40:26 +01:00
Romain Pouclet 98d4075de1 Fixed typo in AbstractQuery::execute() doc 2011-02-25 10:22:02 -06:00
Benjamin Eberlei 81cff239f8 Merge branch 'DDC-1036' into 2.0.x 2011-02-20 09:15:37 +01:00
Guilherme Blanco 46dbce9b6c [DDC-1036] Modified the AggregateExpressions to support SimpleArithmeticExpression instead of StateFieldPathExpression. 2011-02-20 09:15:01 +01:00
Benjamin Eberlei 64129c66e0 Merge branch 'DDC-1030' into 2.0.x 2011-02-13 10:03:00 +01:00
Benjamin Eberlei 479ae3e22a DDC-1030 - Fix Static Reflection with namespace levels deeper than one. 2011-02-13 10:02:49 +01:00
Benjamin Eberlei 0d42c686e1 Merge branch 'DDC-1024' into 2.0.x 2011-02-12 17:44:54 +01:00
Benjamin Eberlei 2ba48d58e7 DDC-1024 - Do not generate setter/getter for inherited fields. 2011-02-12 17:44:39 +01:00
Benjamin Eberlei c3ab35a8f5 Merge branch 'DDC-1018' into 2.0.x 2011-02-05 10:03:48 +01:00
Benjamin Eberlei 6dcbbdae4d [DDC-1018] Bugfix: INDEX BY was not working in JOIN Declarations, only in FROM. 2011-02-05 10:03:22 +01:00
Benjamin Eberlei 4a020f2c48 Merge branch 'DDC-1006' into 2.0.x 2011-02-02 23:31:16 +01:00
Benjamin Eberlei 5e4811a3cd DDC-1008, DDC-1002 - Create constructor and id setter if necessary. 2011-02-02 23:30:57 +01:00
Benjamin Eberlei 1dd85fe19e DDC-1006, DDC-953 - Fix EntityGenerator creating empty classes 2011-02-02 23:30:57 +01:00
Benjamin Eberlei fd7442a056 Merge remote branch 'origin/2.0.x' into 2.0.x 2011-02-02 19:48:54 +01:00
Benjamin Eberlei 1d4b188a52 Fix build.xml 2011-02-02 19:48:08 +01:00
Benjamin Eberlei 6c57ec12ee Bump Dev Version to 2.0.2-DEV 2011-01-30 11:23:07 -05:00
Benjamin Eberlei 7a3ee2a8da Release 2.0.1 2011-01-30 11:22:59 -05:00
Benjamin Eberlei 5e61b73619 Fix version of 2.0.x branch to 2.0.1-DEV 2011-01-30 17:16:30 +01:00
Benjamin Eberlei 23ac0026a0 Merge remote branch 'origin/2.0.x' into 2.0.x 2011-01-30 17:14:35 +01:00
Benjamin Eberlei 65e85aa471 Update dependencies to Common 2.0.1 and DBAL 2.0.1 2011-01-30 17:14:07 +01:00
Benjamin Eberlei d5b61ec897 Update build.xml workflow 2011-01-30 17:11:56 +01:00
Benjamin Eberlei adc2f24c9a Merge branch 'DDC-892' into 2.0.x 2011-01-23 20:54:03 +01:00
Benjamin Eberlei 8423c0c608 DDC-892 - Implement separate chaining approach for result caches to prevent hash colissions. 2011-01-23 20:53:20 +01:00
Benjamin Eberlei 44aa098b37 Merge branch 'GenerationTools' into 2.0.x 2011-01-23 20:27:02 +01:00
Benjamin Eberlei 839ec8f25a Significantly updated the Help of the ConvertMapping and GenerateEntities Commands to help people using and understanding their scope. Added an additional --force flag to ConvertMapping command. 2011-01-23 20:26:56 +01:00
Benjamin Eberlei 0893d2eb00 Merge branch 'DDC-958' into 2.0.x 2011-01-23 17:28:24 +01:00
Benjamin Eberlei b63babc7b8 DDC-958 - Fire postLoad event when calling refresh(). 2011-01-23 17:28:16 +01:00
Benjamin Eberlei 7350d85a4b Merge branch 'DDC-968' into 2.0.x 2011-01-23 16:48:08 +01:00
Benjamin Eberlei a6b81d684a DDC-968 - Add AbstractQuery::getHints() method 2011-01-23 16:47:48 +01:00
Benjamin Eberlei 9e864c3662 Merge branch 'DDC-969' into 2.0.x 2011-01-23 16:13:12 +01:00
Benjamin Eberlei 024cc43189 DDC-969 - Use of field instead of column when accessing a table leads to error when both differ. 2011-01-23 16:12:59 +01:00
Benjamin Eberlei 1e79672147 Merge branch 'DDC-978' into 2.0.x 2011-01-23 15:41:02 +01:00
Benjamin Eberlei 3b7448bcf4 DDC-978 - Fix bug where Collection gets cleared (again) when calling flush multiple times and replacing a PersistentCollection with a new one. 2011-01-23 15:40:54 +01:00
Benjamin Eberlei d5025235f3 Merge branch 'DDC-996' into 2.0.x 2011-01-23 14:24:13 +01:00
Benjamin Eberlei dbc1a4da4b DDC-996 - Throw more useful exception if fieldName is empty in a mapped field or association. 2011-01-23 14:23:25 +01:00
Benjamin Eberlei 837d3f0f80 Merge branch 'DDc-960' into 2.0.x 2011-01-23 12:58:55 +01:00
Benjamin Eberlei 203fb59115 DDC-960 - Bugfix in how Persisters generate Fetch last version of Entity SQL. 2011-01-23 12:58:27 +01:00
Benjamin Eberlei ecdc0fad64 Merge branch 'DDC-975' into 2.0.x 2011-01-13 21:45:44 +01:00
Benjamin Eberlei e1fd2c158b DDC-975 - Fix notice in SchemaTool in combination with XML mapping driver. 2011-01-13 21:45:30 +01:00
Benjamin Eberlei 479dae2a99 Merge branch 'DDC-980' into 2.0.x 2011-01-13 21:18:46 +01:00
Benjamin Eberlei d94c2a11e8 DDC-980 - Fix Update and Delete statements reference of the root table when doing subselects. 2011-01-13 21:18:23 +01:00
Benjamin Eberlei d44b9fb05c Merge branch 'DDC-965' into 2.0.x 2011-01-02 10:25:37 +01:00
Benjamin Eberlei fc16ecc6d7 DDC-965 - Defer ID check after loadMetata event is fired. 2011-01-02 10:25:23 +01:00
Benjamin Eberlei 1c9007fb0e Merge branch 'DDC-966' into 2.0.x 2011-01-02 10:19:06 +01:00
Benjamin Eberlei 79dc69b920 DDC-966 - Fix NOT NULL constraint SingleTableInheritance Generation using SchemaTool. 2011-01-02 10:18:55 +01:00
Benjamin Eberlei 5e22a08ee1 Merge branch 'DDC-949' into 2.0.x 2011-01-02 09:43:21 +01:00
Benjamin Eberlei 3d43049426 DDC-949 - Bugfix for BasicEntityPersister not using $types for select clauses. This fixes the issue for PostgreSQL however it still occurs on Oracle. DBAL change is necessary for this. 2011-01-02 09:43:04 +01:00
Benjamin Eberlei 95464c95fa Merge branch 'DDC-945-2' into 2.0.x 2010-12-31 14:39:49 +01:00
Benjamin Eberlei 392d23e401 DDC-945 - Fix regression, ManyToMany unidirectional owning side assocations should be allowed. 2010-12-31 14:39:38 +01:00
Benjamin Eberlei 19db4f304d Merge branch 'DDC-929' into 2.0.x 2010-12-30 23:18:49 +01:00
Benjamin Eberlei aeaeff9002 DDC-929 - Fix bug with DatabaseDriver not detecting indexes that are not called primary. 2010-12-30 23:18:36 +01:00
Benjamin Eberlei 9bc236b4fa Merge branch 'DDC-961' into 2.0.x 2010-12-30 22:31:39 +01:00
Benjamin Eberlei cd6611ad3e DDC-961 - Bugfix with missing first letter in automatic join table names in global namespace entities. 2010-12-30 22:31:24 +01:00
Benjamin Eberlei 41e5fc6b34 Merge branch 'DDC-837' into 2.0.x 2010-12-28 14:58:56 +01:00
Benjamin Eberlei 615a1159a7 DDC-837 - Fix bug with associations of the same name not being possible in inheritance hierachies. 2010-12-28 14:58:30 +01:00
Benjamin Eberlei 1059991865 Merge branch 'DDC-928' into 2.0.x 2010-12-28 12:20:28 +01:00
Benjamin Eberlei 18fc94b395 DDC-928 - Fix undefined variable notice. 2010-12-28 12:20:10 +01:00
Benjamin Eberlei b288eac530 Merge branch 'DDC-945' into 2.0.x 2010-12-28 12:01:17 +01:00
Benjamin Eberlei 699cd2cf4b DDC-945 - Throw exception in ClassMetadataFactory when mapped superclass has to many associations. 2010-12-28 12:00:42 +01:00
Benjamin Eberlei c1f10b4673 DDC-617 - Throw error if selecting identification variables without picking at least one root entity alias. 2010-12-28 10:21:25 +01:00
Benjamin Eberlei 6bff8c338f DDC-931 - SchemaTool#dropSchema() should not stop on failure of a single query (as stated in docblocks). 2010-12-22 23:07:27 +01:00
Benjamin Eberlei 1ca924d021 Fix for DDC-944 2010-12-22 00:19:03 +01:00
238 changed files with 2345 additions and 12063 deletions
+1
View File
@@ -1,3 +1,4 @@
build.properties
build/
logs/
reports/
+3 -6
View File
@@ -4,12 +4,9 @@
[submodule "lib/vendor/doctrine-dbal"]
path = lib/vendor/doctrine-dbal
url = git://github.com/doctrine/dbal.git
[submodule "lib/vendor/Symfony/Component/Console"]
path = lib/vendor/Symfony/Component/Console
url = git://github.com/symfony/Console.git
[submodule "lib/vendor/Symfony/Component/Yaml"]
path = lib/vendor/Symfony/Component/Yaml
url = git://github.com/symfony/Yaml.git
[submodule "lib/vendor/doctrine-build-common"]
path = lib/vendor/doctrine-build-common
url = https://github.com/doctrine/doctrine-build-common.git
[submodule "lib/vendor/Symfony/Component/Console"]
path = lib/vendor/Symfony/Component/Console
url = git://github.com/symfony/Console.git
-19
View File
@@ -1,19 +0,0 @@
language: php
php:
- 5.3
- 5.4
env:
- DB=mysql
- DB=pgsql
- DB=sqlite
before_script:
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS doctrine_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'DROP DATABASE IF EXISTS doctrine_tests_tmp;' -U postgres; fi"
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'create database doctrine_tests;' -U postgres; fi"
- sh -c "if [ '$DB' = 'pgsql' ]; then psql -c 'create database doctrine_tests_tmp;' -U postgres; fi"
- sh -c "if [ '$DB' = 'mysql' ]; then mysql -e 'create database IF NOT EXISTS doctrine_tests_tmp;create database IF NOT EXISTS doctrine_tests;'; fi"
- git submodule update --init
script: phpunit --configuration tests/travis/$DB.travis.xml
-24
View File
@@ -1,24 +0,0 @@
This document details all the possible changes that you should investigate when updating
your project from Doctrine 2.0.x 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:
\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.
-11
View File
@@ -1,11 +0,0 @@
# Project Name
project.name=DoctrineORM
# Dependency minimum versions
dependencies.common=2.1.0
dependencies.dbal=2.1.0
dependencies.sfconsole=2.0.0
# Version class and file
project.version_class = Doctrine\ORM\Version
project.version_file = lib/Doctrine/ORM/Version.php
+15
View File
@@ -0,0 +1,15 @@
version=2.0.1
dependencies.common=2.0.1
dependencies.dbal=2.0.1
stability=beta
build.dir=build
dist.dir=dist
report.dir=reports
log.archive.dir=logs
project.pirum_dir=
project.download_dir=
test.phpunit_configuration_file=
test.phpunit_generate_coverage=0
test.pmd_reports=0
test.pdepend_exec=
test.phpmd_exec=
+177 -19
View File
@@ -1,7 +1,11 @@
<?xml version="1.0"?>
<project name="DoctrineORM" default="build" basedir=".">
<!--
Doctrine 2 build file.
-->
<project name="Doctrine2" default="build" basedir=".">
<taskdef classname="phing.tasks.ext.d51PearPkg2Task" name="d51pearpkg2" />
<import file="${project.basedir}/lib/vendor/doctrine-build-common/packaging.xml" />
<property file="build.properties" />
@@ -10,8 +14,6 @@
-->
<fileset id="shared-artifacts" dir=".">
<include name="LICENSE"/>
<include name="UPGRADE*" />
<include name="doctrine-mapping.xsd" />
</fileset>
<!--
@@ -49,34 +51,101 @@
-->
<fileset id="symfony-sources" dir="./lib/vendor">
<include name="Symfony/Component/**"/>
<exclude name="**/.git/**" />
</fileset>
<!--
Clean the directory for the next build.
-->
<target name="clean">
<available file="./build.properties" property="build_properties_exist" value="true"/>
<fail unless="build_properties_exist" message="The build.properties file is missing." />
<delete dir="${build.dir}" includeemptydirs="true" />
<delete dir="${dist.dir}" includeemptydirs="true" />
<delete dir="${report.dir}" includeemptydirs="true" />
</target>
<!--
Prepare the new build directories after cleaning
-->
<target name="prepare" depends="clean">
<echo msg="Creating build directory: ${build.dir}" />
<mkdir dir="${build.dir}" />
<echo msg="Creating distribution directory: ${dist.dir}" />
<mkdir dir="${dist.dir}" />
<echo msg="Creating report directory: ${report.dir}" />
<mkdir dir="${report.dir}" />
<mkdir dir="${build.dir}/logs"/>
<mkdir dir="${report.dir}/tests"/>
</target>
<!--
Builds ORM package, preparing it for distribution.
-->
<target name="copy-files" depends="prepare">
<copy todir="${build.dir}/${project.name}-${version}">
<target name="build-orm" depends="prepare">
<exec command="grep '${version}' ${project.basedir}/lib/Doctrine/ORM/Version.php" checkreturn="true"/>
<copy todir="${build.dir}/doctrine-orm">
<fileset refid="shared-artifacts"/>
</copy>
<copy todir="${build.dir}/${project.name}-${version}">
<copy todir="${build.dir}/doctrine-orm">
<fileset refid="common-sources"/>
<fileset refid="dbal-sources"/>
<fileset refid="orm-sources"/>
</copy>
<copy todir="${build.dir}/${project.name}-${version}/Doctrine">
<copy todir="${build.dir}/doctrine-orm/Doctrine">
<fileset refid="symfony-sources"/>
</copy>
<copy todir="${build.dir}/${project.name}-${version}/bin">
<copy todir="${build.dir}/doctrine-orm/bin">
<fileset refid="bin-scripts"/>
</copy>
<exec command="sed 's/${version}-DEV/${version}/' ${build.dir}/doctrine-orm/Doctrine/ORM/Version.php > ${build.dir}/doctrine-orm/Doctrine/ORM/Version2.php" passthru="true" />
<exec command="mv ${build.dir}/doctrine-orm/Doctrine/ORM/Version2.php ${build.dir}/doctrine-orm/Doctrine/ORM/Version.php" passthru="true" />
<delete dir="${build.dir}/doctrine-orm/Doctrine/Symfony/Component/Yaml/.git" includeemptydirs="true"/>
<delete dir="${build.dir}/doctrine-orm/Doctrine/Symfony/Component/Console/.git" includeemptydirs="true"/>
</target>
<target name="build" depends="test, build-orm"/>
<!--
Runs the full test suite.
-->
<target name="test" depends="prepare">
<if><equals arg1="${test.phpunit_generate_coverage}" arg2="1" />
<then>
<property name="test.phpunit_coverage_file" value="${build.dir}/logs/clover.xml" />
</then>
<else>
<property name="test.phpunit_coverage_file" value="false" />
</else>
</if>
<nativephpunit
testfile="./tests/Doctrine/Tests/AllTests.php" junitlogfile="${build.dir}/logs/testsuites.xml"
testdirectory="./tests" coverageclover="${test.phpunit_coverage_file}" configuration="${test.phpunit_configuration_file}"
/>
<phpunitreport infile="${build.dir}/logs/testsuites.xml" format="frames" todir="${report.dir}/tests" />
<nativephpunit testfile="./tests/Doctrine/Tests/ORM/Performance/AllTests.php" testdirectory="./tests" haltonfailure="false" haltonerror="false" />
<tstamp/>
<copy file="${build.dir}/logs/testsuites.xml" tofile="${log.archive.dir}/latest/log.xml" overwrite="true"/>
<if><equals arg1="${test.pmd_reports}" arg2="1" />
<then>
<exec command="${test.pdepend_exec} --jdepend-xml=${build.dir}/logs/jdepend.xml ./lib/Doctrine" />
<exec command="${test.phpmd_exec} ./lib/Doctrine xml codesize --reportfile ${build.dir}/logs/phpmd.xml" />
<copy file="${build.dir}/logs/jdepend.xml" tofile="${log.archive.dir}/latest/jdepend.xml" overwrite="true"/>
<copy file="${build.dir}/logs/phpmd.xml" tofile="${log.archive.dir}/latest/phpmd.xml" overwrite="true"/>
</then>
</if>
</target>
<!--
Builds distributable PEAR packages.
-->
<target name="define-pear-package" depends="copy-files">
<d51pearpkg2 baseinstalldir="/" dir="${build.dir}/${project.name}-${version}">
<target name="build-packages" depends="build-orm">
<d51pearpkg2 baseinstalldir="/" dir="${build.dir}/doctrine-orm">
<name>DoctrineORM</name>
<summary>Doctrine Object Relational Mapper</summary>
<channel>pear.doctrine-project.org</channel>
@@ -86,29 +155,118 @@
<lead user="romanb" name="Roman Borschel" email="roman@code-factory.org" />
<lead user="beberlei" name="Benjamin Eberlei" email="kontakt@beberlei.de" />
<license>LGPL</license>
<version release="${pear.version}" api="${pear.version}" />
<stability release="${pear.stability}" api="${pear.stability}" />
<version release="${version}" api="${version}" />
<stability release="${stability}" api="${stability}" />
<notes>-</notes>
<dependencies>
<php minimum_version="5.3.0" />
<pear minimum_version="1.6.0" recommended_version="1.6.1" />
<package name="DoctrineCommon" channel="pear.doctrine-project.org" minimum_version="${dependencies.common}" />
<package name="DoctrineDBAL" channel="pear.doctrine-project.org" minimum_version="${dependencies.dbal}" />
<package name="Console" channel="pear.symfony.org" minimum_version="2.0.0" />
<package name="Yaml" channel="pear.symfony.org" minimum_version="2.0.0" />
<package name="DoctrineSymfonyConsole" channel="pear.doctrine-project.org" minimum_version="2.0.0" />
<package name="DoctrineSymfonyYaml" channel="pear.doctrine-project.org" minimum_version="2.0.0" />
</dependencies>
<dirroles key="bin">script</dirroles>
<ignore>Doctrine/Common/</ignore>
<ignore>Doctrine/DBAL/</ignore>
<ignore>Symfony/Component/Yaml/</ignore>
<ignore>Symfony/Component/Console/</ignore>
<release>
<install as="doctrine" name="bin/doctrine" />
<install as="doctrine.php" name="bin/doctrine.php" />
<install as="doctrine.bat" name="bin/doctrine.bat" />
</release>
<replacement path="bin/doctrine" type="pear-config" from="@php_bin@" to="php_bin" />
<replacement path="bin/doctrine.bat" type="pear-config" from="@php_bin@" to="php_bin" />
<replacement path="bin/doctrine.bat" type="pear-config" from="@bin_dir@" to="bin_dir" />
</d51pearpkg2>
<exec command="pear package" dir="${build.dir}/doctrine-orm" passthru="true" />
<exec command="mv DoctrineORM-${version}.tgz ../../dist" dir="${build.dir}/doctrine-orm" passthru="true" />
<tar destfile="dist/DoctrineORM-${version}-full.tar.gz" compression="gzip" basedir="${build.dir}">
<fileset dir="${build.dir}">
<include name="**/**" />
<exclude name="logs/" />
<exclude name="doctrine-orm/package.xml" />
</fileset>
</tar>
</target>
<target name="git-tag">
<exec command="grep '${version}-DEV' ${project.basedir}/lib/Doctrine/ORM/Version.php" checkreturn="true"/>
<exec command="sed 's/${version}-DEV/${version}/' ${project.basedir}/lib/Doctrine/ORM/Version.php > ${project.basedir}/lib/Doctrine/ORM/Version2.php" passthru="true" />
<exec command="mv ${project.basedir}/lib/Doctrine/ORM/Version2.php ${project.basedir}/lib/Doctrine/ORM/Version.php" passthru="true" />
<exec command="git add ${project.basedir}/lib/Doctrine/ORM/Version.php" passthru="true" />
<exec command="git commit -m 'Release ${version}'" />
<exec command="git tag -m 'Tag ${version}' -a ${version}" passthru="true" />
</target>
<target name="pirum-release">
<exec command="sudo pirum add ${project.pirum_dir} ${project.basedir}/dist/DoctrineORM-${version}.tgz" dir="." passthru="true" />
<exec command="sudo pirum build ${project.pirum_dir}" passthru="true" />
</target>
<target name="distribute-download">
<copy file="dist/DoctrineORM-${version}-full.tar.gz" todir="${project.download_dir}" />
</target>
<target name="update-dev-version">
<exec command="grep '${version}' ${project.basedir}/lib/Doctrine/ORM/Version.php" checkreturn="true"/>
<propertyprompt propertyName="next_version" defaultValue="${version}" promptText="Enter next version string (without -DEV)" />
<exec command="sed 's/${version}/${next_version}-DEV/' ${project.basedir}/lib/Doctrine/ORM/Version.php > ${project.basedir}/lib/Doctrine/ORM/Version2.php" passthru="true" />
<exec command="mv ${project.basedir}/lib/Doctrine/ORM/Version2.php ${project.basedir}/lib/Doctrine/ORM/Version.php" passthru="true" />
<exec command="git add ${project.basedir}/lib/Doctrine/ORM/Version.php" passthru="true" />
<exec command="git commit -m 'Bump Dev Version to ${next_version}-DEV'" passthru="true" />
</target>
<target name="release" depends="git-tag,build-packages,distribute-download,pirum-release,update-dev-version" />
<!--
Builds distributable PEAR packages for the Symfony Dependencies
-->
<target name="release-symfony-dependencies" depends="build-orm">
<d51pearpkg2 baseinstalldir="/" dir="${build.dir}/doctrine-orm">
<name>DoctrineSymfonyConsole</name>
<summary>Symfony Console Component</summary>
<channel>pear.doctrine-project.org</channel>
<description>A command line interface tool from the Symfony project. Packaged for shipping with Doctrine projects using ORM version numbers.</description>
<lead user="fabpot" name="Fabien Potencier" email="fabien.potencier@symfony-project.com" />
<license>NewBSD License</license>
<version release="${version}" api="${version}" />
<stability release="${stability}" api="${stability}" />
<notes>-</notes>
<dependencies>
<php minimum_version="5.3.0" />
<pear minimum_version="1.6.0" recommended_version="1.6.1" />
</dependencies>
<ignore>Doctrine/Common/</ignore>
<ignore>Doctrine/DBAL/</ignore>
<ignore>Doctrine/ORM/</ignore>
<ignore>Symfony/Component/Yaml/</ignore>
</d51pearpkg2>
<exec command="pear package" dir="${build.dir}/doctrine-orm" passthru="true" />
<exec command="mv DoctrineSymfonyConsole-${version}.tgz ../../dist" dir="${build.dir}/doctrine-orm" passthru="true" />
<d51pearpkg2 baseinstalldir="/" dir="${build.dir}/doctrine-orm">
<name>DoctrineSymfonyYaml</name>
<summary>Symfony Yaml Component</summary>
<channel>pear.doctrine-project.org</channel>
<description>A YAML Parser from the Symfony project. Packaged for shipping with Doctrine projects using ORM version numbers.</description>
<lead user="fabpot" name="Fabien Potencier" email="fabien.potencier@symfony-project.com" />
<license>NewBSD License</license>
<version release="${version}" api="${version}" />
<stability release="${stability}" api="${stability}" />
<notes>-</notes>
<dependencies>
<php minimum_version="5.3.0" />
<pear minimum_version="1.6.0" recommended_version="1.6.1" />
</dependencies>
<ignore>Doctrine/Common/</ignore>
<ignore>Doctrine/DBAL/</ignore>
<ignore>Doctrine/ORM/</ignore>
<ignore>Symfony/Component/Console/</ignore>
</d51pearpkg2>
<exec command="pear package" dir="${build.dir}/doctrine-orm" passthru="true" />
<exec command="mv DoctrineSymfonyYaml-${version}.tgz ../../dist" dir="${build.dir}/doctrine-orm" passthru="true" />
<exec command="sudo pirum add ${project.pirum_dir} ${project.basedir}/dist/DoctrineSymfonyConsole-${version}.tgz" dir="." passthru="true" />
<exec command="sudo pirum add ${project.pirum_dir} ${project.basedir}/dist/DoctrineSymfonyYaml-${version}.tgz" dir="." passthru="true" />
<exec command="sudo pirum build ${project.pirum_dir}" passthru="true" />
</target>
</project>
-23
View File
@@ -1,23 +0,0 @@
{
"name": "doctrine/orm",
"type": "library","version":"2.1.5",
"description": "Object-Relational-Mapper for PHP",
"keywords": ["orm", "database"],
"homepage": "http://www.doctrine-project.org",
"license": "LGPL",
"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"}
],
"require": {
"php": ">=5.3.2",
"ext-pdo": "*",
"doctrine/common": "2.1.*",
"doctrine/dbal": "2.1.*"
},
"autoload": {
"psr-0": { "Doctrine\\ORM": "lib/" }
}
}
+7 -110
View File
@@ -17,18 +17,11 @@
<xs:sequence>
<xs:element name="mapped-superclass" type="orm:mapped-superclass" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="entity" type="orm:entity" minOccurs="0" maxOccurs="unbounded" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
</xs:element>
<xs:complexType name="emptyType">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="emptyType"/>
<xs:complexType name="cascade-type">
<xs:sequence>
@@ -37,9 +30,7 @@
<xs:element name="cascade-merge" type="orm:emptyType" minOccurs="0"/>
<xs:element name="cascade-remove" type="orm:emptyType" minOccurs="0"/>
<xs:element name="cascade-refresh" type="orm:emptyType" minOccurs="0"/>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:simpleType name="lifecycle-callback-type">
@@ -55,32 +46,13 @@
</xs:simpleType>
<xs:complexType name="lifecycle-callback">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="type" type="orm:lifecycle-callback-type" use="required" />
<xs:attribute name="method" type="xs:NMTOKEN" use="required" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="lifecycle-callbacks">
<xs:sequence>
<xs:element name="lifecycle-callback" type="orm:lifecycle-callback" minOccurs="1" maxOccurs="unbounded" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="named-query">
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="query" type="xs:string" use="required" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="named-queries">
<xs:sequence>
<xs:element name="named-query" type="orm:named-query" minOccurs="1" maxOccurs="unbounded" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
</xs:complexType>
@@ -91,14 +63,12 @@
<xs:element name="discriminator-column" type="orm:discriminator-column" minOccurs="0"/>
<xs:element name="discriminator-map" type="orm:discriminator-map" minOccurs="0"/>
<xs:element name="lifecycle-callbacks" type="orm:lifecycle-callbacks" minOccurs="0" maxOccurs="1" />
<xs:element name="named-queries" type="orm:named-queries" minOccurs="0" maxOccurs="1" />
<xs:element name="id" type="orm:id" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="id" type="orm:id" minOccurs="0" maxOccurs="1" />
<xs:element name="field" type="orm:field" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="one-to-one" type="orm:one-to-one" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="one-to-many" type="orm:one-to-many" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="many-to-one" type="orm:many-to-one" minOccurs="0" maxOccurs="unbounded" />
<xs:element name="many-to-many" type="orm:many-to-many" minOccurs="0" maxOccurs="unbounded" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" use="required" />
<xs:attribute name="table" type="xs:NMTOKEN" />
@@ -106,18 +76,11 @@
<xs:attribute name="repository-class" type="xs:string"/>
<xs:attribute name="inheritance-type" type="orm:inheritance-type"/>
<xs:attribute name="change-tracking-policy" type="orm:change-tracking-policy" />
<xs:attribute name="read-only" type="xs:boolean" default="false" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="mapped-superclass" >
<xs:complexContent>
<xs:extension base="orm:entity">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:anyAttribute namespace="##other"/>
</xs:extension>
<xs:extension base="orm:entity"/>
</xs:complexContent>
</xs:complexType>
@@ -158,14 +121,10 @@
<xs:restriction base="xs:token">
<xs:enumeration value="EAGER"/>
<xs:enumeration value="LAZY"/>
<xs:enumeration value="EXTRALAZY"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="field">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="type" type="xs:NMTOKEN" default="string" />
<xs:attribute name="column" type="xs:NMTOKEN" />
@@ -176,114 +135,75 @@
<xs:attribute name="column-definition" type="xs:string" />
<xs:attribute name="precision" type="xs:integer" use="optional" />
<xs:attribute name="scale" type="xs:integer" use="optional" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="discriminator-column">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="type" type="xs:NMTOKEN" use="required" />
<xs:attribute name="field-name" type="xs:NMTOKEN" />
<xs:attribute name="length" type="xs:NMTOKEN" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="unique-constraint">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="name" type="xs:NMTOKEN" use="optional"/>
<xs:attribute name="columns" type="xs:string" use="required"/>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="unique-constraints">
<xs:sequence>
<xs:element name="unique-constraint" type="orm:unique-constraint" minOccurs="1" maxOccurs="unbounded"/>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="index">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="name" type="xs:NMTOKEN" use="optional"/>
<xs:attribute name="columns" type="xs:string" use="required"/>
<xs:anyAttribute namespace="##other"/>
<xs:attribute name="columns" type="xs:NMTOKENS" use="required"/>
</xs:complexType>
<xs:complexType name="indexes">
<xs:sequence>
<xs:element name="index" type="orm:index" minOccurs="1" maxOccurs="unbounded"/>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="discriminator-mapping">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="value" type="xs:NMTOKEN" use="required"/>
<xs:attribute name="class" type="xs:string" use="required"/>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="discriminator-map">
<xs:sequence>
<xs:element name="discriminator-mapping" type="orm:discriminator-mapping" minOccurs="1" maxOccurs="unbounded"/>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="generator">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="strategy" type="orm:generator-strategy" use="optional" default="AUTO" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="id">
<xs:sequence>
<xs:element name="generator" type="orm:generator" minOccurs="0" />
<xs:element name="sequence-generator" type="orm:sequence-generator" minOccurs="0" maxOccurs="1" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="type" type="xs:NMTOKEN" />
<xs:attribute name="type" type="xs:NMTOKEN" use="required" />
<xs:attribute name="column" type="xs:NMTOKEN" />
<xs:attribute name="association-key" type="xs:boolean" default="false" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="sequence-generator">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="sequence-name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="allocation-size" type="xs:integer" use="optional" default="1" />
<xs:attribute name="initial-value" type="xs:integer" use="optional" default="1" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="inverse-join-columns">
<xs:sequence>
<xs:element name="join-column" type="orm:join-column" minOccurs="1" maxOccurs="unbounded" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="join-column">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="referenced-column-name" type="xs:NMTOKEN" use="optional" default="id" />
<xs:attribute name="unique" type="xs:boolean" default="false" />
@@ -291,43 +211,32 @@
<xs:attribute name="on-delete" type="orm:fk-action" />
<xs:attribute name="on-update" type="orm:fk-action" />
<xs:attribute name="column-definition" type="xs:string" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="join-columns">
<xs:sequence>
<xs:element name="join-column" type="orm:join-column" minOccurs="1" maxOccurs="unbounded" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="join-table">
<xs:sequence>
<xs:element name="join-columns" type="orm:join-columns" />
<xs:element name="inverse-join-columns" type="orm:join-columns" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="schema" type="xs:NMTOKEN" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="order-by">
<xs:sequence>
<xs:element name="order-by-field" type="orm:order-by-field" minOccurs="1" maxOccurs="unbounded" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="order-by-field">
<xs:sequence>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="direction" type="orm:order-by-direction" default="ASC" />
<xs:anyAttribute namespace="##other"/>
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
<xs:attribute name="direction" type="orm:order-by-direction" default="ASC" />
</xs:complexType>
<xs:simpleType name="order-by-direction">
@@ -342,30 +251,24 @@
<xs:element name="cascade" type="orm:cascade-type" minOccurs="0" />
<xs:element name="join-table" type="orm:join-table" minOccurs="0" />
<xs:element name="order-by" type="orm:order-by" minOccurs="0" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="target-entity" type="xs:string" use="required" />
<xs:attribute name="field" type="xs:NMTOKEN" use="required" />
<xs:attribute name="mapped-by" type="xs:NMTOKEN" />
<xs:attribute name="index-by" type="xs:NMTOKEN" />
<xs:attribute name="inversed-by" type="xs:NMTOKEN" />
<xs:attribute name="fetch" type="orm:fetch-type" default="LAZY" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="one-to-many">
<xs:sequence>
<xs:element name="cascade" type="orm:cascade-type" minOccurs="0" />
<xs:element name="order-by" type="orm:order-by" minOccurs="0" />
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="target-entity" type="xs:string" use="required" />
<xs:attribute name="mapped-by" type="xs:NMTOKEN" use="required" />
<xs:attribute name="field" type="xs:NMTOKEN" use="required" />
<xs:attribute name="index-by" type="xs:NMTOKEN" />
<xs:attribute name="orphan-removal" type="xs:boolean" default="false" />
<xs:attribute name="fetch" type="orm:fetch-type" default="LAZY" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="many-to-one">
@@ -374,16 +277,13 @@
<xs:choice minOccurs="0" maxOccurs="1">
<xs:element name="join-column" type="orm:join-column"/>
<xs:element name="join-columns" type="orm:join-columns"/>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="target-entity" type="xs:string" use="required" />
<xs:attribute name="field" type="xs:NMTOKEN" use="required" />
<xs:attribute name="orphan-removal" type="xs:boolean" default="false" />
<xs:attribute name="fetch" type="orm:fetch-type" default="LAZY" />
<xs:attribute name="inversed-by" type="xs:NMTOKEN" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
<xs:complexType name="one-to-one">
@@ -392,9 +292,7 @@
<xs:choice minOccurs="0" maxOccurs="1">
<xs:element name="join-column" type="orm:join-column"/>
<xs:element name="join-columns" type="orm:join-columns"/>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:choice>
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
</xs:sequence>
<xs:attribute name="field" type="xs:NMTOKEN" use="required" />
<xs:attribute name="target-entity" type="xs:string" use="required" />
@@ -402,7 +300,6 @@
<xs:attribute name="inversed-by" type="xs:NMTOKEN" />
<xs:attribute name="orphan-removal" type="xs:boolean" default="false" />
<xs:attribute name="fetch" type="orm:fetch-type" default="LAZY" />
<xs:anyAttribute namespace="##other"/>
</xs:complexType>
</xs:schema>
+26 -94
View File
@@ -1,5 +1,7 @@
<?php
/*
* $Id: Abstract.php 1393 2008-03-06 17:49:16Z guilhermeblanco $
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -55,11 +57,6 @@ abstract class AbstractQuery
*/
const HYDRATE_SINGLE_SCALAR = 4;
/**
* Very simple object hydrator (optimized for performance).
*/
const HYDRATE_SIMPLEOBJECT = 5;
/**
* @var array The parameter map of this query.
*/
@@ -76,7 +73,7 @@ abstract class AbstractQuery
protected $_resultSetMapping;
/**
* @var \Doctrine\ORM\EntityManager The entity manager used by this query object.
* @var Doctrine\ORM\EntityManager The entity manager used by this query object.
*/
protected $_em;
@@ -122,7 +119,7 @@ abstract class AbstractQuery
/**
* Initializes a new instance of a class derived from <tt>AbstractQuery</tt>.
*
* @param \Doctrine\ORM\EntityManager $entityManager
* @param Doctrine\ORM\EntityManager $entityManager
*/
public function __construct(EntityManager $em)
{
@@ -132,7 +129,7 @@ abstract class AbstractQuery
/**
* Retrieves the associated EntityManager of this Query instance.
*
* @return \Doctrine\ORM\EntityManager
* @return Doctrine\ORM\EntityManager
*/
public function getEntityManager()
{
@@ -162,16 +159,6 @@ abstract class AbstractQuery
{
return $this->_params;
}
/**
* Get all defined parameter types.
*
* @return array The defined query parameter types.
*/
public function getParameterTypes()
{
return $this->_paramTypes;
}
/**
* Gets a query parameter.
@@ -184,17 +171,6 @@ abstract class AbstractQuery
return isset($this->_params[$key]) ? $this->_params[$key] : null;
}
/**
* Gets a query parameter type.
*
* @param mixed $key The key (index or name) of the bound parameter.
* @return mixed The parameter type of the bound parameter.
*/
public function getParameterType($key)
{
return isset($this->_paramTypes[$key]) ? $this->_paramTypes[$key] : null;
}
/**
* Gets the SQL query that corresponds to this query object.
* The returned SQL syntax depends on the connection driver that is used
@@ -212,17 +188,14 @@ abstract class AbstractQuery
* @param string $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 \Doctrine\ORM\AbstractQuery This query instance.
* @return Doctrine\ORM\AbstractQuery This query instance.
*/
public function setParameter($key, $value, $type = null)
{
if ($type === null) {
$type = Query\ParameterTypeInferer::inferType($value);
if ($type !== null) {
$this->_paramTypes[$key] = $type;
}
$this->_paramTypes[$key] = $type;
$this->_params[$key] = $value;
return $this;
}
@@ -231,7 +204,7 @@ abstract class AbstractQuery
*
* @param array $params
* @param array $types
* @return \Doctrine\ORM\AbstractQuery This query instance.
* @return Doctrine\ORM\AbstractQuery This query instance.
*/
public function setParameters(array $params, array $types = array())
{
@@ -249,7 +222,7 @@ abstract class AbstractQuery
* Sets the ResultSetMapping that should be used for hydration.
*
* @param ResultSetMapping $rsm
* @return \Doctrine\ORM\AbstractQuery
* @return Doctrine\ORM\AbstractQuery
*/
public function setResultSetMapping(Query\ResultSetMapping $rsm)
{
@@ -260,8 +233,8 @@ abstract class AbstractQuery
/**
* Defines a cache driver to be used for caching result sets.
*
* @param \Doctrine\Common\Cache\Cache $driver Cache driver
* @return \Doctrine\ORM\AbstractQuery
* @param Doctrine\Common\Cache\Cache $driver Cache driver
* @return Doctrine\ORM\AbstractQuery
*/
public function setResultCacheDriver($resultCacheDriver = null)
{
@@ -278,7 +251,7 @@ abstract class AbstractQuery
/**
* Returns the cache driver used for caching result sets.
*
* @return \Doctrine\Common\Cache\Cache Cache driver
* @return Doctrine\Common\Cache\Cache Cache driver
*/
public function getResultCacheDriver()
{
@@ -296,7 +269,7 @@ abstract class AbstractQuery
* @param boolean $bool
* @param integer $timeToLive
* @param string $resultCacheId
* @return \Doctrine\ORM\AbstractQuery This query instance.
* @return This query instance.
*/
public function useResultCache($bool, $timeToLive = null, $resultCacheId = null)
{
@@ -314,7 +287,7 @@ abstract class AbstractQuery
* Defines how long the result cache will be active before expire.
*
* @param integer $timeToLive How long the cache entry is valid.
* @return \Doctrine\ORM\AbstractQuery This query instance.
* @return Doctrine\ORM\AbstractQuery This query instance.
*/
public function setResultCacheLifetime($timeToLive)
{
@@ -340,7 +313,7 @@ abstract class AbstractQuery
* Defines if the result cache is active or not.
*
* @param boolean $expire Whether or not to force resultset cache expiration.
* @return \Doctrine\ORM\AbstractQuery This query instance.
* @return Doctrine\ORM\AbstractQuery This query instance.
*/
public function expireResultCache($expire = true)
{
@@ -358,32 +331,12 @@ abstract class AbstractQuery
return $this->_expireResultCache;
}
/**
* 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 AbstractQuery
*/
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 integer $hydrationMode Doctrine processing mode to be used during hydration process.
* One of the Query::HYDRATE_* constants.
* @return \Doctrine\ORM\AbstractQuery This query instance.
* @return Doctrine\ORM\AbstractQuery This query instance.
*/
public function setHydrationMode($hydrationMode)
{
@@ -437,31 +390,6 @@ abstract class AbstractQuery
return $this->execute(array(), self::HYDRATE_SCALAR);
}
/**
* Get exactly one result or null.
*
* @throws NonUniqueResultException
* @param int $hydrationMode
* @return mixed
*/
public function getOneOrNullResult($hydrationMode = null)
{
$result = $this->execute(array(), $hydrationMode);
if ($this->_hydrationMode !== self::HYDRATE_SINGLE_SCALAR && ! $result) {
return null;
}
if (is_array($result)) {
if (count($result) > 1) {
throw new NonUniqueResultException;
}
return array_shift($result);
}
return $result;
}
/**
* Gets the single result of the query.
*
@@ -511,7 +439,7 @@ abstract class AbstractQuery
*
* @param string $name The name of the hint.
* @param mixed $value The value of the hint.
* @return \Doctrine\ORM\AbstractQuery
* @return Doctrine\ORM\AbstractQuery
*/
public function setHint($name, $value)
{
@@ -582,6 +510,10 @@ abstract class AbstractQuery
$this->setParameters($params);
}
if (isset($this->_params[0])) {
throw QueryException::invalidParameterPosition(0);
}
// Check result cache
if ($this->_useResultCache && $cacheDriver = $this->getResultCacheDriver()) {
list($key, $hash) = $this->getResultCacheId();
@@ -592,8 +524,8 @@ abstract class AbstractQuery
$stmt = $this->_doExecute();
$result = $this->_em->getHydrator($this->_hydrationMode)->hydrateAll(
$stmt, $this->_resultSetMapping, $this->_hints
);
$stmt, $this->_resultSetMapping, $this->_hints
);
$cacheDriver->save($hash, array($key => $result), $this->_resultCacheTTL);
@@ -621,7 +553,7 @@ abstract class AbstractQuery
* generated for you.
*
* @param string $id
* @return \Doctrine\ORM\AbstractQuery This query instance.
* @return Doctrine\ORM\AbstractQuery This query instance.
*/
public function setResultCacheId($id)
{
@@ -667,7 +599,7 @@ abstract class AbstractQuery
/**
* Executes the query and returns a the resulting Statement object.
*
* @return \Doctrine\DBAL\Driver\Statement The executed database statement that holds the results.
* @return Doctrine\DBAL\Driver\Statement The executed database statement that holds the results.
*/
abstract protected function _doExecute();
+13 -47
View File
@@ -20,12 +20,7 @@
namespace Doctrine\ORM;
use Doctrine\Common\Cache\Cache,
Doctrine\Common\Cache\ArrayCache,
Doctrine\Common\Annotations\AnnotationRegistry,
Doctrine\Common\Annotations\AnnotationReader,
Doctrine\Common\Annotations\SimpleAnnotationReader,
Doctrine\ORM\Mapping\Driver\Driver,
Doctrine\ORM\Mapping\Driver\AnnotationDriver;
Doctrine\ORM\Mapping\Driver\Driver;
/**
* Configuration container for all configuration options of Doctrine.
@@ -86,7 +81,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
/**
* Gets the namespace where proxy classes reside.
*
*
* @return string
*/
public function getProxyNamespace()
@@ -97,7 +92,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
/**
* Sets the namespace where proxy classes reside.
*
*
* @param string $ns
*/
public function setProxyNamespace($ns)
@@ -119,35 +114,16 @@ class Configuration extends \Doctrine\DBAL\Configuration
/**
* Add a new default annotation driver with a correctly configured annotation reader.
*
*
* @param array $paths
* @return Mapping\Driver\AnnotationDriver
*/
public function newDefaultAnnotationDriver($paths = array())
{
if (version_compare(\Doctrine\Common\Version::VERSION, '2.2.0-DEV', '>=')) {
// Register the ORM Annotations in the AnnotationRegistry
AnnotationRegistry::registerFile(__DIR__ . '/Mapping/Driver/DoctrineAnnotations.php');
$reader = new SimpleAnnotationReader();
$reader->addNamespace('Doctrine\ORM\Mapping');
$reader = new \Doctrine\Common\Annotations\CachedReader($reader, new ArrayCache());
} else if (version_compare(\Doctrine\Common\Version::VERSION, '2.1.0-DEV', '>=')) {
// Register the ORM Annotations in the AnnotationRegistry
AnnotationRegistry::registerFile(__DIR__ . '/Mapping/Driver/DoctrineAnnotations.php');
$reader = new AnnotationReader();
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
$reader->setIgnoreNotImportedAnnotations(true);
$reader->setEnableParsePhpImports(false);
$reader = new \Doctrine\Common\Annotations\CachedReader(
new \Doctrine\Common\Annotations\IndexedReader($reader), new ArrayCache()
);
} else {
$reader = new AnnotationReader();
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
}
return new AnnotationDriver($reader, (array)$paths);
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
return new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader, (array)$paths);
}
/**
@@ -164,7 +140,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
/**
* Resolves a registered namespace alias to the full namespace.
*
* @param string $entityNamespaceAlias
* @param string $entityNamespaceAlias
* @return string
* @throws MappingException
*/
@@ -188,16 +164,6 @@ class Configuration extends \Doctrine\DBAL\Configuration
$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.
*
@@ -362,7 +328,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
/**
* Gets the implementation class name of a registered custom string DQL function.
*
*
* @param string $name
* @return string
*/
@@ -405,7 +371,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
/**
* Gets the implementation class name of a registered custom numeric DQL function.
*
*
* @param string $name
* @return string
*/
@@ -448,7 +414,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
/**
* Gets the implementation class name of a registered custom date/time DQL function.
*
*
* @param string $name
* @return string
*/
@@ -499,7 +465,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
/**
* Set a class metadata factory.
*
*
* @param string $cmf
*/
public function setClassMetadataFactoryName($cmfName)
+29 -47
View File
@@ -21,7 +21,6 @@ namespace Doctrine\ORM;
use Closure, Exception,
Doctrine\Common\EventManager,
Doctrine\Common\Persistence\ObjectManager,
Doctrine\DBAL\Connection,
Doctrine\DBAL\LockMode,
Doctrine\ORM\Mapping\ClassMetadata,
@@ -38,26 +37,26 @@ use Closure, Exception,
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class EntityManager implements ObjectManager
class EntityManager
{
/**
* The used Configuration.
*
* @var \Doctrine\ORM\Configuration
* @var Doctrine\ORM\Configuration
*/
private $config;
/**
* The database connection used by the EntityManager.
*
* @var \Doctrine\DBAL\Connection
* @var Doctrine\DBAL\Connection
*/
private $conn;
/**
* The metadata factory, used to retrieve the ORM metadata of entity classes.
*
* @var \Doctrine\ORM\Mapping\ClassMetadataFactory
* @var Doctrine\ORM\Mapping\ClassMetadataFactory
*/
private $metadataFactory;
@@ -71,14 +70,14 @@ class EntityManager implements ObjectManager
/**
* The UnitOfWork used to coordinate object-level transactions.
*
* @var \Doctrine\ORM\UnitOfWork
* @var Doctrine\ORM\UnitOfWork
*/
private $unitOfWork;
/**
* The event manager that is the central point of the event system.
*
* @var \Doctrine\Common\EventManager
* @var Doctrine\Common\EventManager
*/
private $eventManager;
@@ -92,14 +91,14 @@ class EntityManager implements ObjectManager
/**
* The proxy factory used to create dynamic proxies.
*
* @var \Doctrine\ORM\Proxy\ProxyFactory
* @var Doctrine\ORM\Proxy\ProxyFactory
*/
private $proxyFactory;
/**
* The expression builder instance used to generate query expressions.
*
* @var \Doctrine\ORM\Query\Expr
* @var Doctrine\ORM\Query\Expr
*/
private $expressionBuilder;
@@ -114,9 +113,9 @@ class EntityManager implements ObjectManager
* 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
* @param Doctrine\DBAL\Connection $conn
* @param Doctrine\ORM\Configuration $config
* @param Doctrine\Common\EventManager $eventManager
*/
protected function __construct(Connection $conn, Configuration $config, EventManager $eventManager)
{
@@ -128,7 +127,7 @@ class EntityManager implements ObjectManager
$this->metadataFactory = new $metadataFactoryClassName;
$this->metadataFactory->setEntityManager($this);
$this->metadataFactory->setCacheDriver($this->config->getMetadataCacheImpl());
$this->unitOfWork = new UnitOfWork($this);
$this->proxyFactory = new ProxyFactory($this,
$config->getProxyDir(),
@@ -139,7 +138,7 @@ class EntityManager implements ObjectManager
/**
* Gets the database connection object used by the EntityManager.
*
* @return \Doctrine\DBAL\Connection
* @return Doctrine\DBAL\Connection
*/
public function getConnection()
{
@@ -149,7 +148,7 @@ class EntityManager implements ObjectManager
/**
* Gets the metadata factory used to gather the metadata of classes.
*
* @return \Doctrine\ORM\Mapping\ClassMetadataFactory
* @return Doctrine\ORM\Mapping\ClassMetadataFactory
*/
public function getMetadataFactory()
{
@@ -168,7 +167,7 @@ class EntityManager implements ObjectManager
* ->where($expr->orX($expr->eq('u.id', 1), $expr->eq('u.id', 2)));
* </code>
*
* @return \Doctrine\ORM\Query\Expr
* @return Doctrine\ORM\Query\Expr
*/
public function getExpressionBuilder()
{
@@ -203,18 +202,13 @@ class EntityManager implements ObjectManager
public function transactional(Closure $func)
{
$this->conn->beginTransaction();
try {
$return = $func($this);
$func($this);
$this->flush();
$this->conn->commit();
return $return ?: true;
} catch (Exception $e) {
$this->close();
$this->conn->rollback();
throw $e;
}
}
@@ -244,12 +238,12 @@ class EntityManager implements ObjectManager
*
* 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
*
* @return \Doctrine\ORM\Mapping\ClassMetadata
* @return Doctrine\ORM\Mapping\ClassMetadata
* @internal Performance-sensitive method.
*/
public function getClassMetadata($className)
@@ -261,7 +255,7 @@ class EntityManager implements ObjectManager
* Creates a new Query object.
*
* @param string The DQL string.
* @return \Doctrine\ORM\Query
* @return Doctrine\ORM\Query
*/
public function createQuery($dql = "")
{
@@ -276,7 +270,7 @@ class EntityManager implements ObjectManager
* Creates a Query from a named query.
*
* @param string $name
* @return \Doctrine\ORM\Query
* @return Doctrine\ORM\Query
*/
public function createNamedQuery($name)
{
@@ -302,7 +296,7 @@ class EntityManager implements ObjectManager
* Creates a NativeQuery from a named native query.
*
* @param string $name
* @return \Doctrine\ORM\NativeQuery
* @return Doctrine\ORM\NativeQuery
*/
public function createNamedNativeQuery($name)
{
@@ -325,7 +319,7 @@ class EntityManager implements ObjectManager
* This effectively synchronizes the in-memory state of managed objects with the
* database.
*
* @throws \Doctrine\ORM\OptimisticLockException If a version check on an entity that
* @throws Doctrine\ORM\OptimisticLockException If a version check on an entity that
* makes use of optimistic locking fails.
*/
public function flush()
@@ -413,7 +407,6 @@ class EntityManager implements ObjectManager
$entity = $class->newInstance();
$class->setIdentifierValues($entity, $identifier);
$this->unitOfWork->registerManaged($entity, $identifier, array());
$this->unitOfWork->markReadOnly($entity);
return $entity;
}
@@ -450,7 +443,7 @@ class EntityManager implements ObjectManager
*
* 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.
*
@@ -601,7 +594,7 @@ class EntityManager implements ObjectManager
/**
* Gets the EventManager used by the EntityManager.
*
* @return \Doctrine\Common\EventManager
* @return Doctrine\Common\EventManager
*/
public function getEventManager()
{
@@ -611,7 +604,7 @@ class EntityManager implements ObjectManager
/**
* Gets the Configuration used by the EntityManager.
*
* @return \Doctrine\ORM\Configuration
* @return Doctrine\ORM\Configuration
*/
public function getConfiguration()
{
@@ -632,7 +625,7 @@ class EntityManager implements ObjectManager
/**
* Check if the Entity manager is open or closed.
*
*
* @return bool
*/
public function isOpen()
@@ -643,7 +636,7 @@ class EntityManager implements ObjectManager
/**
* Gets the UnitOfWork used by the EntityManager to coordinate operations.
*
* @return \Doctrine\ORM\UnitOfWork
* @return Doctrine\ORM\UnitOfWork
*/
public function getUnitOfWork()
{
@@ -657,7 +650,7 @@ class EntityManager implements ObjectManager
* selectively iterate over the result.
*
* @param int $hydrationMode
* @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
* @return Doctrine\ORM\Internal\Hydration\AbstractHydrator
*/
public function getHydrator($hydrationMode)
{
@@ -672,7 +665,7 @@ class EntityManager implements ObjectManager
* Create a new instance for the given hydration mode.
*
* @param int $hydrationMode
* @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
* @return Doctrine\ORM\Internal\Hydration\AbstractHydrator
*/
public function newHydrator($hydrationMode)
{
@@ -689,9 +682,6 @@ class EntityManager implements ObjectManager
case Query::HYDRATE_SINGLE_SCALAR:
$hydrator = new Internal\Hydration\SingleScalarHydrator($this);
break;
case Query::HYDRATE_SIMPLEOBJECT:
$hydrator = new Internal\Hydration\SimpleObjectHydrator($this);
break;
default:
if ($class = $this->config->getCustomHydrationMode($hydrationMode)) {
$hydrator = new $class($this);
@@ -713,14 +703,6 @@ class EntityManager implements ObjectManager
return $this->proxyFactory;
}
/**
* {@inheritDoc}
*/
public function initializeObject($entity)
{
$this->unitOfWork->initializeObject($entity);
}
/**
* Factory method to create EntityManager instances.
*
+8 -23
View File
@@ -20,7 +20,6 @@
namespace Doctrine\ORM;
use Doctrine\DBAL\LockMode;
use Doctrine\Common\Persistence\ObjectRepository;
/**
* An EntityRepository serves as a repository for entities with generic as well as
@@ -35,7 +34,7 @@ use Doctrine\Common\Persistence\ObjectRepository;
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class EntityRepository implements ObjectRepository
class EntityRepository
{
/**
* @var string
@@ -48,7 +47,7 @@ class EntityRepository implements ObjectRepository
protected $_em;
/**
* @var \Doctrine\ORM\Mapping\ClassMetadata
* @var Doctrine\ORM\Mapping\ClassMetadata
*/
protected $_class;
@@ -78,17 +77,6 @@ class EntityRepository implements ObjectRepository
->from($this->_entityName, $alias);
}
/**
* Create 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));
}
/**
* Clears the repository, causing all managed entities to become detached.
*/
@@ -112,7 +100,7 @@ class EntityRepository implements ObjectRepository
if (!($entity instanceof $this->_class->name)) {
return null;
}
if ($lockMode != LockMode::NONE) {
$this->_em->lock($entity, $lockMode, $lockVersion);
}
@@ -141,7 +129,7 @@ class EntityRepository implements ObjectRepository
if (!$this->_em->getConnection()->isTransactionActive()) {
throw TransactionRequiredException::transactionRequired();
}
return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($id, null, null, array(), $lockMode);
}
}
@@ -160,14 +148,11 @@ class EntityRepository implements ObjectRepository
* 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.
* @return array
*/
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
public function findBy(array $criteria)
{
return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->loadAll($criteria, $orderBy, $limit, $offset);
return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->loadAll($criteria);
}
/**
@@ -241,4 +226,4 @@ class EntityRepository implements ObjectRepository
{
return $this->_class;
}
}
}
@@ -1,54 +0,0 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Event;
/**
* Provides event arguments for the onClear event.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.com
* @since 2.0
* @version $Revision$
* @author Roman Borschel <roman@code-factory.de>
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class OnClearEventArgs extends \Doctrine\Common\EventArgs
{
/**
* @var \Doctrine\ORM\EntityManager
*/
private $em;
/**
* @param \Doctrine\ORM\EntityManager $em
*/
public function __construct($em)
{
$this->em = $em;
}
/**
* @return \Doctrine\ORM\EntityManager
*/
public function getEntityManager()
{
return $this->em;
}
}
-8
View File
@@ -119,12 +119,4 @@ final class Events
* @var string
*/
const onFlush = 'onFlush';
/**
* 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';
}
+1 -1
View File
@@ -26,7 +26,7 @@ abstract class AbstractIdGenerator
/**
* Generates an identifier for an entity.
*
* @param \Doctrine\ORM\Entity $entity
* @param Doctrine\ORM\Entity $entity
* @return mixed
*/
abstract public function generate(EntityManager $em, $entity);
+3 -21
View File
@@ -47,18 +47,9 @@ class AssignedGenerator extends AbstractIdGenerator
if ($class->isIdentifierComposite) {
$idFields = $class->getIdentifierFieldNames();
foreach ($idFields as $idField) {
$value = $class->reflFields[$idField]->getValue($entity);
$value = $class->getReflectionProperty($idField)->getValue($entity);
if (isset($value)) {
if (isset($class->associationMappings[$idField])) {
if (!$em->getUnitOfWork()->isInIdentityMap($value)) {
throw ORMException::entityMissingForeignAssignedId($entity, $value);
}
// NOTE: Single Columns as associated identifiers only allowed - this constraint it is enforced.
$identifier[$idField] = current($em->getUnitOfWork()->getEntityIdentifier($value));
} else {
$identifier[$idField] = $value;
}
$identifier[$idField] = $value;
} else {
throw ORMException::entityMissingAssignedId($entity);
}
@@ -67,16 +58,7 @@ class AssignedGenerator extends AbstractIdGenerator
$idField = $class->identifier[0];
$value = $class->reflFields[$idField]->getValue($entity);
if (isset($value)) {
if (isset($class->associationMappings[$idField])) {
if (!$em->getUnitOfWork()->isInIdentityMap($value)) {
throw ORMException::entityMissingForeignAssignedId($entity, $value);
}
// NOTE: Single Columns as associated identifiers only allowed - this constraint it is enforced.
$identifier[$idField] = current($em->getUnitOfWork()->getEntityIdentifier($value));
} else {
$identifier[$idField] = $value;
}
$identifier[$idField] = $value;
} else {
throw ORMException::entityMissingAssignedId($entity);
}
+1 -1
View File
@@ -37,7 +37,7 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
/**
* Initializes a new sequence generator.
*
* @param \Doctrine\ORM\EntityManager $em The EntityManager to use.
* @param Doctrine\ORM\EntityManager $em The EntityManager to use.
* @param string $sequenceName The name of the sequence.
* @param integer $allocationSize The allocation size of the sequence.
*/
@@ -58,7 +58,7 @@ abstract class AbstractHydrator
/**
* Initializes a new instance of a class derived from <tt>AbstractHydrator</tt>.
*
* @param \Doctrine\ORM\EntityManager $em The EntityManager to use.
* @param Doctrine\ORM\EntityManager $em The EntityManager to use.
*/
public function __construct(EntityManager $em)
{
@@ -164,11 +164,6 @@ abstract class AbstractHydrator
* field names during this procedure as well as any necessary conversions on
* the values applied.
*
* @param array $data SQL Result Row
* @param array &$cache Cache for column to field result information
* @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.
*/
@@ -195,12 +190,9 @@ abstract class AbstractHydrator
continue;
} else {
// Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns).
$fieldName = $this->_rsm->metaMappings[$key];
$cache[$key]['isMetaColumn'] = true;
$cache[$key]['fieldName'] = $fieldName;
$cache[$key]['fieldName'] = $this->_rsm->metaMappings[$key];
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
$classMetadata = $this->_em->getClassMetadata($this->_rsm->aliasMap[$cache[$key]['dqlAlias']]);
$cache[$key]['isIdentifier'] = isset($this->_rsm->isIdentifierColumn[$cache[$key]['dqlAlias']][$key]);
}
}
@@ -211,25 +203,13 @@ abstract class AbstractHydrator
$dqlAlias = $cache[$key]['dqlAlias'];
if ($cache[$key]['isIdentifier']) {
$id[$dqlAlias] .= '|' . $value;
if (isset($cache[$key]['isMetaColumn'])) {
$rowData[$dqlAlias][$cache[$key]['fieldName']] = $value;
continue;
}
if (isset($cache[$key]['isMetaColumn'])) {
if ( ! isset($rowData[$dqlAlias][$cache[$key]['fieldName']]) && $value !== null) {
$rowData[$dqlAlias][$cache[$key]['fieldName']] = $value;
if ($cache[$key]['isIdentifier']) {
$nonemptyComponents[$dqlAlias] = true;
}
}
continue;
}
// in an inheritance hierachy the same field could be defined several times.
// We overwrite this value so long we dont 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[$dqlAlias][$cache[$key]['fieldName']]) && $value === null) {
continue;
if ($cache[$key]['isIdentifier']) {
$id[$dqlAlias] .= '|' . $value;
}
$rowData[$dqlAlias][$cache[$key]['fieldName']] = $cache[$key]['type']->convertToPHPValue($value, $this->_platform);
@@ -295,25 +275,4 @@ abstract class AbstractHydrator
return $rowData;
}
protected function registerManaged($class, $entity, $data)
{
if ($class->isIdentifierComposite) {
$id = array();
foreach ($class->identifier as $fieldName) {
if (isset($class->associationMappings[$fieldName])) {
$id[$fieldName] = $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']];
} else {
$id[$fieldName] = $data[$fieldName];
}
}
} else {
if (isset($class->associationMappings[$class->identifier[0]])) {
$id = array($class->identifier[0] => $data[$class->associationMappings[$class->identifier[0]]['joinColumns'][0]['name']]);
} else {
$id = array($class->identifier[0] => $data[$class->identifier[0]]);
}
}
$this->_em->getUnitOfWork()->registerManaged($entity, $id, $data);
}
}
@@ -92,11 +92,6 @@ class ArrayHydrator extends AbstractHydrator
$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])) {
@@ -159,17 +154,6 @@ class ArrayHydrator extends AbstractHydrator
// It's a root result element
$this->_rootAliases[$dqlAlias] = true; // Mark as root
// 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[] = array(0 => null);
} else {
$result[] = null;
}
++$this->_resultCounter;
continue;
}
// Check for an existing element
if ($this->_isSimpleQuery || ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
@@ -29,7 +29,7 @@ namespace Doctrine\ORM\Internal\Hydration;
class IterableResult implements \Iterator
{
/**
* @var \Doctrine\ORM\Internal\Hydration\AbstractHydrator
* @var Doctrine\ORM\Internal\Hydration\AbstractHydrator
*/
private $_hydrator;
@@ -49,7 +49,7 @@ class IterableResult implements \Iterator
private $_current = null;
/**
* @param \Doctrine\ORM\Internal\Hydration\AbstractHydrator $hydrator
* @param Doctrine\ORM\Internal\Hydration\AbstractHydrator $hydrator
*/
public function __construct($hydrator)
{
@@ -24,8 +24,7 @@ use PDO,
Doctrine\ORM\PersistentCollection,
Doctrine\ORM\Query,
Doctrine\Common\Collections\ArrayCollection,
Doctrine\Common\Collections\Collection,
Doctrine\ORM\Proxy\Proxy;
Doctrine\Common\Collections\Collection;
/**
* The ObjectHydrator constructs an object graph out of an SQL result set.
@@ -60,9 +59,6 @@ class ObjectHydrator extends AbstractHydrator
$this->_resultPointers =
$this->_idTemplate = array();
$this->_resultCounter = 0;
if (!isset($this->_hints['deferEagerLoad'])) {
$this->_hints['deferEagerLoad'] = true;
}
foreach ($this->_rsm->aliasMap as $dqlAlias => $className) {
$this->_identifierMap[$dqlAlias] = array();
@@ -83,18 +79,26 @@ class ObjectHydrator extends AbstractHydrator
$sourceClassName = $this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]];
$sourceClass = $this->_getClassMetadata($sourceClassName);
$assoc = $sourceClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]];
$this->_hints['fetched'][$this->_rsm->parentAliasMap[$dqlAlias]][$assoc['fieldName']] = true;
$this->_hints['fetched'][$sourceClassName][$assoc['fieldName']] = true;
if ($sourceClass->subClasses) {
foreach ($sourceClass->subClasses as $sourceSubclassName) {
$this->_hints['fetched'][$sourceSubclassName][$assoc['fieldName']] = true;
}
}
if ($assoc['type'] != ClassMetadata::MANY_TO_MANY) {
// Mark any non-collection opposite sides as fetched, too.
if ($assoc['mappedBy']) {
$this->_hints['fetched'][$dqlAlias][$assoc['mappedBy']] = true;
$this->_hints['fetched'][$className][$assoc['mappedBy']] = true;
} else {
if ($assoc['inversedBy']) {
$inverseAssoc = $class->associationMappings[$assoc['inversedBy']];
if ($inverseAssoc['type'] & ClassMetadata::TO_ONE) {
$this->_hints['fetched'][$dqlAlias][$inverseAssoc['fieldName']] = true;
$this->_hints['fetched'][$className][$inverseAssoc['fieldName']] = true;
if ($class->subClasses) {
foreach ($class->subClasses as $targetSubclassName) {
$this->_hints['fetched'][$targetSubclassName][$inverseAssoc['fieldName']] = true;
}
}
}
}
}
@@ -108,17 +112,11 @@ class ObjectHydrator extends AbstractHydrator
*/
protected function _cleanup()
{
$eagerLoad = (isset($this->_hints['deferEagerLoad'])) && $this->_hints['deferEagerLoad'] == true;
parent::_cleanup();
$this->_identifierMap =
$this->_initializedCollections =
$this->_existingCollections =
$this->_resultPointers = array();
if ($eagerLoad) {
$this->_em->getUnitOfWork()->triggerEagerLoads();
}
}
/**
@@ -147,7 +145,7 @@ class ObjectHydrator extends AbstractHydrator
* @param object $entity The entity to which the collection belongs.
* @param string $name The name of the field on the entity that holds the collection.
*/
private function _initRelatedCollection($entity, $class, $fieldName, $parentDqlAlias)
private function _initRelatedCollection($entity, $class, $fieldName)
{
$oid = spl_object_hash($entity);
$relation = $class->associationMappings[$fieldName];
@@ -168,7 +166,7 @@ class ObjectHydrator extends AbstractHydrator
$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]) &&
isset($this->_hints['fetched'][$class->name][$fieldName]) &&
! $value->isInitialized()) {
// Is already PersistentCollection, but either REFRESH or FETCH-JOIN and UNINITIALIZED!
$value->setDirty(false);
@@ -185,7 +183,7 @@ class ObjectHydrator extends AbstractHydrator
/**
* Gets an entity instance.
*
*
* @param $data The instance data.
* @param $dqlAlias The DQL alias of the entity's class.
* @return object The entity.
@@ -198,33 +196,18 @@ class ObjectHydrator extends AbstractHydrator
$className = $this->_ce[$className]->discriminatorMap[$data[$discrColumn]];
unset($data[$discrColumn]);
}
if (isset($this->_hints[Query::HINT_REFRESH_ENTITY]) && isset($this->_rootAliases[$dqlAlias])) {
$class = $this->_ce[$className];
$this->registerManaged($class, $this->_hints[Query::HINT_REFRESH_ENTITY], $data);
}
$this->_hints['fetchAlias'] = $dqlAlias;
return $this->_uow->createEntity($className, $data, $this->_hints);
}
private function _getEntityFromIdentityMap($className, array $data)
{
// TODO: Abstract this code and UnitOfWork::createEntity() equivalent?
$class = $this->_ce[$className];
/* @var $class ClassMetadata */
if ($class->isIdentifierComposite) {
$idHash = '';
foreach ($class->identifier as $fieldName) {
if (isset($class->associationMappings[$fieldName])) {
$idHash .= $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']] . ' ';
} else {
$idHash .= $data[$fieldName] . ' ';
}
$idHash .= $data[$fieldName] . ' ';
}
return $this->_uow->tryGetByIdHash(rtrim($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);
} else {
return $this->_uow->tryGetByIdHash($data[$class->identifier[0]], $class->rootEntityName);
}
@@ -234,7 +217,7 @@ class ObjectHydrator extends AbstractHydrator
* Gets a ClassMetadata instance from the local cache.
* If the instance is not yet in the local cache, it is loaded into the
* local cache.
*
*
* @param string $className The name of the class.
* @return ClassMetadata
*/
@@ -248,21 +231,21 @@ class ObjectHydrator extends AbstractHydrator
/**
* 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.
*
* specified by the FROM clause in a DQL query.
*
* @param array $data The data of the row to process.
* @param array $cache The cache to use.
* @param array $result The result array to fill.
@@ -296,16 +279,10 @@ class ObjectHydrator extends AbstractHydrator
// 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;
}
// Get a reference to the parent object to which the joined element belongs.
if ($this->_rsm->isMixed && isset($this->_rootAliases[$parentAlias])) {
$first = reset($this->_resultPointers);
$parentObject = $first[key($first)];
$parentObject = $this->_resultPointers[$parentAlias][key($first)];
} else if (isset($this->_resultPointers[$parentAlias])) {
$parentObject = $this->_resultPointers[$parentAlias];
} else {
@@ -313,7 +290,6 @@ class ObjectHydrator extends AbstractHydrator
continue;
}
$parentClass = $this->_ce[$this->_rsm->aliasMap[$parentAlias]];
$oid = spl_object_hash($parentObject);
$relationField = $this->_rsm->relationMap[$dqlAlias];
@@ -328,7 +304,7 @@ class ObjectHydrator extends AbstractHydrator
if (isset($this->_initializedCollections[$collKey])) {
$reflFieldValue = $this->_initializedCollections[$collKey];
} else if ( ! isset($this->_existingCollections[$collKey])) {
$reflFieldValue = $this->_initRelatedCollection($parentObject, $parentClass, $relationField, $parentAlias);
$reflFieldValue = $this->_initRelatedCollection($parentObject, $parentClass, $relationField);
}
$indexExists = isset($this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]]);
@@ -364,14 +340,15 @@ class ObjectHydrator extends AbstractHydrator
$this->_resultPointers[$dqlAlias] = $reflFieldValue[$index];
}
} else if ( ! $reflField->getValue($parentObject)) {
$reflFieldValue = $this->_initRelatedCollection($parentObject, $parentClass, $relationField, $parentAlias);
$coll = new PersistentCollection($this->_em, $this->_ce[$entityName], new ArrayCollection);
$coll->setOwner($parentObject, $relation);
$reflField->setValue($parentObject, $coll);
$this->_uow->setOriginalEntityProperty($oid, $relationField, $coll);
}
} 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 unitialized proxy.
if ( ! $reflFieldValue || isset($this->_hints[Query::HINT_REFRESH])) {
if (isset($nonemptyComponents[$dqlAlias])) {
$element = $this->_getEntity($data, $dqlAlias);
$reflField->setValue($parentObject, $element);
@@ -397,8 +374,6 @@ class ObjectHydrator extends AbstractHydrator
}
// Update result pointer
$this->_resultPointers[$dqlAlias] = $element;
} else {
$this->_uow->setOriginalEntityProperty($oid, $relationField, null);
}
// else leave $reflFieldValue null for single-valued associations
} else {
@@ -410,18 +385,6 @@ class ObjectHydrator extends AbstractHydrator
// PATH C: Its a root result element
$this->_rootAliases[$dqlAlias] = true; // Mark as root alias
// 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[] = array(0 => null);
} else {
$result[] = null;
}
++$this->_resultCounter;
continue;
}
// check for existing result from the iterations before
if ( ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
$element = $this->_getEntity($rowData[$dqlAlias], $dqlAlias);
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
@@ -436,10 +399,6 @@ class ObjectHydrator extends AbstractHydrator
$result[$key] = $element;
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $key;
}
if (isset($this->_hints['collection'])) {
$this->_hints['collection']->hydrateSet($key, $element);
}
} else {
if ($this->_rsm->isMixed) {
$element = array(0 => $element);
@@ -447,10 +406,6 @@ class ObjectHydrator extends AbstractHydrator
$result[] = $element;
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $this->_resultCounter;
++$this->_resultCounter;
if (isset($this->_hints['collection'])) {
$this->_hints['collection']->hydrateAdd($element);
}
}
// Update result pointer
@@ -1,131 +0,0 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Internal\Hydration;
use \PDO;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\DBAL\Types\Type;
use Doctrine\ORM\Query;
class SimpleObjectHydrator extends AbstractHydrator
{
/**
* @var ClassMetadata
*/
private $class;
private $declaringClasses = array();
protected function _hydrateAll()
{
$result = array();
$cache = array();
while ($row = $this->_stmt->fetch(PDO::FETCH_ASSOC)) {
$this->_hydrateRow($row, $cache, $result);
}
$this->_em->getUnitOfWork()->triggerEagerLoads();
return $result;
}
protected function _prepare()
{
if (count($this->_rsm->aliasMap) == 1) {
$this->class = $this->_em->getClassMetadata(reset($this->_rsm->aliasMap));
if ($this->class->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) {
foreach ($this->_rsm->declaringClasses AS $column => $class) {
$this->declaringClasses[$column] = $this->_em->getClassMetadata($class);
}
}
} else {
throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping not containing exactly one object result.");
}
if ($this->_rsm->scalarMappings) {
throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping that contains scalar mappings.");
}
}
protected function _hydrateRow(array $sqlResult, array &$cache, array &$result)
{
$data = array();
if ($this->class->inheritanceType == ClassMetadata::INHERITANCE_TYPE_NONE) {
foreach ($sqlResult as $column => $value) {
if (!isset($cache[$column])) {
if (isset($this->_rsm->fieldMappings[$column])) {
$cache[$column]['name'] = $this->_rsm->fieldMappings[$column];
$cache[$column]['field'] = true;
} else {
$cache[$column]['name'] = $this->_rsm->metaMappings[$column];
}
}
if (isset($cache[$column]['field'])) {
$value = Type::getType($this->class->fieldMappings[$cache[$column]['name']]['type'])
->convertToPHPValue($value, $this->_platform);
}
$data[$cache[$column]['name']] = $value;
}
$entityName = $this->class->name;
} else {
$discrColumnName = $this->_platform->getSQLResultCasing($this->class->discriminatorColumn['name']);
$entityName = $this->class->discriminatorMap[$sqlResult[$discrColumnName]];
unset($sqlResult[$discrColumnName]);
foreach ($sqlResult as $column => $value) {
if (!isset($cache[$column])) {
if (isset($this->_rsm->fieldMappings[$column])) {
$field = $this->_rsm->fieldMappings[$column];
$class = $this->declaringClasses[$column];
if ($class->name == $entityName || is_subclass_of($entityName, $class->name)) {
$cache[$column]['name'] = $field;
$cache[$column]['class'] = $class;
}
} else if (isset($this->_rsm->relationMap[$column])) {
if ($this->_rsm->relationMap[$column] == $entityName || is_subclass_of($entityName, $this->_rsm->relationMap[$column])) {
$cache[$column]['name'] = $field;
}
} else {
$cache[$column]['name'] = $this->_rsm->metaMappings[$column];
}
}
if (isset($cache[$column]['class'])) {
$value = Type::getType($cache[$column]['class']->fieldMappings[$cache[$column]['name']]['type'])
->convertToPHPValue($value, $this->_platform);
}
// the second and part is to prevent overwrites in case of multiple
// inheritance classes using the same property name (See AbstractHydrator)
if (isset($cache[$column]) && (!isset($data[$cache[$column]['name']]) || $value !== null)) {
$data[$cache[$column]['name']] = $value;
}
}
}
if (isset($this->_hints[Query::HINT_REFRESH_ENTITY])) {
$this->registerManaged($this->class, $this->_hints[Query::HINT_REFRESH_ENTITY], $data);
}
$result[] = $this->_em->getUnitOfWork()->createEntity($entityName, $data, $this->_hints);
}
}
+43 -13
View File
@@ -63,10 +63,10 @@ class ClassMetadata extends ClassMetadataInfo
*/
public function __construct($entityName)
{
parent::__construct($entityName);
$this->reflClass = new ReflectionClass($entityName);
$this->namespace = $this->reflClass->getNamespaceName();
$this->table['name'] = $this->reflClass->getShortName();
parent::__construct($this->reflClass->getName()); // do not use $entityName, possible case-problems
}
/**
@@ -205,6 +205,48 @@ class ClassMetadata extends ClassMetadataInfo
$this->reflFields[$sourceFieldName] = $refProp;
}
/**
* Gets the (possibly quoted) column name of a mapped field for safe use
* in an SQL statement.
*
* @param string $field
* @param 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.
*
* @param 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.
*
* @param AbstractPlatform $platform
* @return string
*/
public function getQuotedJoinTableName(array $assoc, $platform)
{
return isset($assoc['joinTable']['quoted'])
? $platform->quoteIdentifier($assoc['joinTable']['name'])
: $assoc['joinTable']['name'];
}
/**
* Creates a string representation of this instance.
*
@@ -275,10 +317,6 @@ class ClassMetadata extends ClassMetadataInfo
$serialized[] = 'isMappedSuperclass';
}
if ($this->containsForeignIdentifier) {
$serialized[] = 'containsForeignIdentifier';
}
if ($this->isVersioned) {
$serialized[] = 'isVersioned';
$serialized[] = 'versionField';
@@ -288,14 +326,6 @@ class ClassMetadata extends ClassMetadataInfo
$serialized[] = 'lifecycleCallbacks';
}
if ($this->namedQueries) {
$serialized[] = 'namedQueries';
}
if ($this->isReadOnly) {
$serialized[] = 'isReadOnly';
}
return $serialized;
}
@@ -23,8 +23,7 @@ use ReflectionException,
Doctrine\ORM\ORMException,
Doctrine\ORM\EntityManager,
Doctrine\DBAL\Platforms,
Doctrine\ORM\Events,
Doctrine\Common\Persistence\Mapping\ClassMetadataFactory as ClassMetadataFactoryInterface;
Doctrine\ORM\Events;
/**
* The ClassMetadataFactory is used to create ClassMetadata objects that contain all the
@@ -37,13 +36,13 @@ use ReflectionException,
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class ClassMetadataFactory implements ClassMetadataFactoryInterface
class ClassMetadataFactory
{
/**
* @var EntityManager
*/
private $em;
/**
* @var AbstractPlatform
*/
@@ -73,7 +72,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
* @var bool
*/
private $initialized = false;
/**
* @param EntityManager $$em
*/
@@ -85,7 +84,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
/**
* Sets the cache driver used by the factory to cache ClassMetadata instances.
*
* @param \Doctrine\Common\Cache\Cache $cacheDriver
* @param Doctrine\Common\Cache\Cache $cacheDriver
*/
public function setCacheDriver($cacheDriver)
{
@@ -95,22 +94,22 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
/**
* Gets the cache driver used by the factory to cache ClassMetadata instances.
*
* @return \Doctrine\Common\Cache\Cache
* @return Doctrine\Common\Cache\Cache
*/
public function getCacheDriver()
{
return $this->cacheDriver;
}
public function getLoadedMetadata()
{
return $this->loadedMetadata;
}
/**
* Forces the factory to load the metadata of all classes known to the underlying
* mapping driver.
*
*
* @return array The ClassMetadata instances of all mapped classes.
*/
public function getAllMetadata()
@@ -143,7 +142,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
* Gets the class metadata descriptor for a class.
*
* @param string $className The name of the class.
* @return \Doctrine\ORM\Mapping\ClassMetadata
* @return Doctrine\ORM\Mapping\ClassMetadata
*/
public function getMetadataFor($className)
{
@@ -188,7 +187,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
/**
* Checks whether the factory has the metadata for a class loaded already.
*
*
* @param string $className
* @return boolean TRUE if the metadata of the class in question is already loaded, FALSE otherwise.
*/
@@ -199,7 +198,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
/**
* 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
@@ -248,13 +247,11 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
// Move down the hierarchy of parent classes, starting from the topmost class
$parent = null;
$rootEntityFound = false;
$visited = array();
foreach ($parentClasses as $className) {
if (isset($this->loadedMetadata[$className])) {
$parent = $this->loadedMetadata[$className];
if ( ! $parent->isMappedSuperclass) {
$rootEntityFound = true;
array_unshift($visited, $className);
}
continue;
@@ -263,15 +260,19 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
$class = $this->newClassMetadataInstance($className);
if ($parent) {
$class->setInheritanceType($parent->inheritanceType);
$class->setDiscriminatorColumn($parent->discriminatorColumn);
if (!$parent->isMappedSuperclass) {
$class->setInheritanceType($parent->inheritanceType);
$class->setDiscriminatorColumn($parent->discriminatorColumn);
}
$class->setIdGeneratorType($parent->generatorType);
$this->addInheritedFields($class, $parent);
$this->addInheritedRelations($class, $parent);
$class->setIdentifier($parent->identifier);
$class->setVersioned($parent->isVersioned);
$class->setVersionField($parent->versionField);
$class->setDiscriminatorMap($parent->discriminatorMap);
if (!$parent->isMappedSuperclass) {
$class->setDiscriminatorMap($parent->discriminatorMap);
}
$class->setLifecycleCallbacks($parent->lifecycleCallbacks);
$class->setChangeTrackingPolicy($parent->changeTrackingPolicy);
}
@@ -283,10 +284,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
throw MappingException::reflectionFailure($className, $e);
}
// If this class has a parent the id generator strategy is inherited.
// However this is only true if the hierachy of parents contains the root entity,
// if it consinsts of mapped superclasses these don't necessarily include the id field.
if ($parent && $rootEntityFound) {
if ($parent && ! $parent->isMappedSuperclass) {
if ($parent->isIdGeneratorSequence()) {
$class->setSequenceGeneratorDefinition($parent->sequenceGeneratorDefinition);
} else if ($parent->isIdGeneratorTable()) {
@@ -306,10 +304,6 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
$class->setPrimaryTable($parent->table);
}
if ($parent && $parent->containsForeignIdentifier) {
$class->containsForeignIdentifier = true;
}
$class->setParentClasses($visited);
if ($this->evm->hasListeners(Events::loadClassMetadata)) {
@@ -317,14 +311,26 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
$this->evm->dispatchEvent(Events::loadClassMetadata, $eventArgs);
}
$this->validateRuntimeMetadata($class, $parent);
// Verify & complete identifier mapping
if ( ! $class->identifier && ! $class->isMappedSuperclass) {
throw MappingException::identifierRequired($className);
}
// verify inheritance
if (!$parent && !$class->isMappedSuperclass && !$class->isInheritanceTypeNone()) {
if (count($class->discriminatorMap) == 0) {
throw MappingException::missingDiscriminatorMap($class->name);
}
if (!$class->discriminatorColumn) {
throw MappingException::missingDiscriminatorColumn($class->name);
}
}
$this->loadedMetadata[$className] = $class;
$parent = $class;
if ( ! $class->isMappedSuperclass) {
$rootEntityFound = true;
array_unshift($visited, $className);
}
@@ -334,43 +340,11 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
return $loaded;
}
/**
* Validate runtime metadata is correctly defined.
*
* @param ClassMetadata $class
* @param ClassMetadata $parent
*/
protected function validateRuntimeMetadata($class, $parent)
{
// Verify & complete identifier mapping
if ( ! $class->identifier && ! $class->isMappedSuperclass) {
throw MappingException::identifierRequired($class->name);
}
// 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 ($parent && !$class->reflClass->isAbstract() && !in_array($class->name, array_values($class->discriminatorMap))) {
// enforce discriminator map for all entities of an inheritance hierachy, otherwise problems will occur.
throw MappingException::mappedClassNotPartOfDiscriminatorMap($class->name, $class->rootEntityName);
}
} 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 hierachy
throw MappingException::noInheritanceOnMappedSuperClass($class->name);
}
}
/**
* Creates a new ClassMetadata instance for the given class name.
*
* @param string $className
* @return \Doctrine\ORM\Mapping\ClassMetadata
* @return Doctrine\ORM\Mapping\ClassMetadata
*/
protected function newClassMetadataInstance($className)
{
@@ -380,8 +354,8 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
/**
* Adds inherited fields to the subclass mapping.
*
* @param \Doctrine\ORM\Mapping\ClassMetadata $subClass
* @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass
* @param Doctrine\ORM\Mapping\ClassMetadata $subClass
* @param Doctrine\ORM\Mapping\ClassMetadata $parentClass
*/
private function addInheritedFields(ClassMetadata $subClass, ClassMetadata $parentClass)
{
@@ -402,8 +376,8 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
/**
* Adds inherited association mappings to the subclass mapping.
*
* @param \Doctrine\ORM\Mapping\ClassMetadata $subClass
* @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass
* @param Doctrine\ORM\Mapping\ClassMetadata $subClass
* @param Doctrine\ORM\Mapping\ClassMetadata $parentClass
*/
private function addInheritedRelations(ClassMetadata $subClass, ClassMetadata $parentClass)
{
@@ -430,7 +404,7 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
* Completes the ID generator mapping. If "auto" is specified we choose the generator
* most appropriate for the targeted database platform.
*
* @param \Doctrine\ORM\Mapping\ClassMetadata $class
* @param Doctrine\ORM\Mapping\ClassMetadata $class
*/
private function completeIdGeneratorMapping(ClassMetadataInfo $class)
{
@@ -482,22 +456,4 @@ class ClassMetadataFactory implements ClassMetadataFactoryInterface
throw new ORMException("Unknown generator type: " . $class->generatorType);
}
}
/**
* {@inheritDoc}
*/
public function isTransient($class)
{
if ( ! $this->initialized) {
$this->initialize();
}
// Check for namespace alias
if (strpos($class, ':') !== false) {
list($namespaceAlias, $simpleClassName) = explode(':', $class);
$class = $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName;
}
return $this->driver->isTransient($class);
}
}
+40 -417
View File
@@ -19,7 +19,6 @@
namespace Doctrine\ORM\Mapping;
use Doctrine\Common\Persistence\Mapping\ClassMetadata;
use ReflectionClass;
/**
@@ -40,7 +39,7 @@ use ReflectionClass;
* @author Jonathan H. Wage <jonwage@gmail.com>
* @since 2.0
*/
class ClassMetadataInfo implements ClassMetadata
class ClassMetadataInfo
{
/* The inheritance mapping types */
/**
@@ -119,15 +118,9 @@ class ClassMetadataInfo implements ClassMetadata
const FETCH_LAZY = 2;
/**
* Specifies that an association is to be fetched when the owner of the
* association is fetched.
* 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.
*/
@@ -204,13 +197,6 @@ class ClassMetadataInfo implements ClassMetadata
*/
public $subClasses = array();
/**
* READ-ONLY: The named queries allowed to be called directly from Repository.
*
* @var array
*/
public $namedQueries = array();
/**
* READ-ONLY: The field names of all fields that are part of the identifier/primary key
* of the mapped entity class.
@@ -269,7 +255,7 @@ class ClassMetadataInfo implements ClassMetadata
* - <b>scale</b> (integer, optional, schema-only)
* The scale of a decimal column. Only valid if the column type is decimal.
*
[* - <b>'unique'] (string, optional, schema-only)</b>
* - <b>unique (string, optional, schema-only)</b>
* Whether a unique constraint should be generated for the column.
*
* @var array
@@ -335,6 +321,7 @@ class ClassMetadataInfo implements ClassMetadata
* uniqueConstraints => array
*
* @var array
* @todo Rename to just $table
*/
public $table;
@@ -361,7 +348,7 @@ class ClassMetadataInfo implements ClassMetadata
* - <b>mappedBy</b> (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.
*
*
* - <b>inversedBy</b> (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.
@@ -383,12 +370,7 @@ class ClassMetadataInfo implements ClassMetadata
* 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.
*
* - <b>indexBy</b> (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:
* <pre>
* array(
@@ -410,15 +392,6 @@ class ClassMetadataInfo implements ClassMetadata
*/
public $isIdentifierComposite = false;
/**
* READ-ONLY: Flag indicating wheather 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.
*
@@ -430,7 +403,7 @@ class ClassMetadataInfo implements ClassMetadata
/**
* READ-ONLY: The definition of the sequence generator of this class. Only used for the
* SEQUENCE generation strategy.
*
*
* The definition has the following structure:
* <code>
* array(
@@ -483,17 +456,6 @@ class ClassMetadataInfo implements ClassMetadata
*/
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;
/**
* Initializes a new ClassMetadata instance that will hold the object-relational mapping
* metadata of the class with the given name.
@@ -672,32 +634,6 @@ class ClassMetadataInfo implements ClassMetadata
$this->fieldNames[$columnName] : $columnName;
}
/**
* Gets the named query.
*
* @see ClassMetadataInfo::$namedQueries
* @throws MappingException
* @param string $queryName The query name
* @return string
*/
public function getNamedQuery($queryName)
{
if ( ! isset($this->namedQueries[$queryName])) {
throw MappingException::queryNotFound($this->name, $queryName);
}
return $this->namedQueries[$queryName];
}
/**
* Gets all named queries of the class.
*
* @return array
*/
public function getNamedQueries()
{
return $this->namedQueries;
}
/**
* Validates & completes the given field mapping.
*
@@ -766,46 +702,14 @@ class ClassMetadataInfo implements ClassMetadata
}
$mapping['isOwningSide'] = true; // assume owning side until we hit mappedBy
// unset optional indexBy attribute if its empty
if (!isset($mapping['indexBy']) || !$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'])) {
if (strlen($this->namespace) > 0 && strpos($mapping['targetEntity'], '\\') === false) {
$mapping['targetEntity'] = $this->namespace . '\\' . $mapping['targetEntity'];
}
$mapping['targetEntity'] = ltrim($mapping['targetEntity'], '\\');
if (isset($mapping['targetEntity']) && strpos($mapping['targetEntity'], '\\') === false
&& strlen($this->namespace) > 0) {
$mapping['targetEntity'] = $this->namespace . '\\' . $mapping['targetEntity'];
}
// Complete id mapping
if (isset($mapping['id']) && $mapping['id'] === true) {
if (isset($mapping['orphanRemoval']) && $mapping['orphanRemoval'] == true) {
throw MappingException::illegalOrphanRemovalOnIdentifierAssociation($this->name, $mapping['fieldName']);
}
if ( ! in_array($mapping['fieldName'], $this->identifier)) {
if (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;
}
}
// Mandatory attributes for both sides
// Mandatory: fieldName, targetEntity
if ( ! isset($mapping['fieldName']) || strlen($mapping['fieldName']) == 0) {
throw MappingException::missingFieldName($this->name);
@@ -813,7 +717,7 @@ class ClassMetadataInfo implements ClassMetadata
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']) {
@@ -825,18 +729,14 @@ class ClassMetadataInfo implements ClassMetadata
} else {
$mapping['isOwningSide'] = false;
}
if (isset($mapping['id']) && $mapping['id'] === true && $mapping['type'] & self::TO_MANY) {
throw MappingException::illegalToManyIdentifierAssoaction($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']) : array();
$cascades = isset($mapping['cascade']) ? $mapping['cascade'] : array();
if (in_array('all', $cascades)) {
$cascades = array(
'remove',
@@ -852,7 +752,7 @@ class ClassMetadataInfo implements ClassMetadata
$mapping['isCascadeRefresh'] = in_array('refresh', $cascades);
$mapping['isCascadeMerge'] = in_array('merge', $cascades);
$mapping['isCascadeDetach'] = in_array('detach', $cascades);
return $mapping;
}
@@ -866,11 +766,11 @@ class ClassMetadataInfo implements ClassMetadata
protected function _validateAndCompleteOneToOneMapping(array $mapping)
{
$mapping = $this->_validateAndCompleteAssociationMapping($mapping);
if (isset($mapping['joinColumns']) && $mapping['joinColumns']) {
$mapping['isOwningSide'] = true;
}
if ($mapping['isOwningSide']) {
if ( ! isset($mapping['joinColumns']) || ! $mapping['joinColumns']) {
// Apply default join column
@@ -879,15 +779,9 @@ class ClassMetadataInfo implements ClassMetadata
'referencedColumnName' => 'id'
));
}
$uniqueContraintColumns = array();
foreach ($mapping['joinColumns'] as $key => &$joinColumn) {
if ($mapping['type'] === self::ONE_TO_ONE) {
if (count($mapping['joinColumns']) == 1) {
$joinColumn['unique'] = true;
} else {
$uniqueContraintColumns[] = $joinColumn['name'];
}
$joinColumn['unique'] = true;
}
if (empty($joinColumn['name'])) {
$joinColumn['name'] = $mapping['fieldName'] . '_id';
@@ -899,25 +793,12 @@ class ClassMetadataInfo implements ClassMetadata
$mapping['joinColumnFieldNames'][$joinColumn['name']] = isset($joinColumn['fieldName'])
? $joinColumn['fieldName'] : $joinColumn['name'];
}
if ($uniqueContraintColumns) {
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"] = array(
'columns' => $uniqueContraintColumns
);
}
$mapping['targetToSourceKeyColumns'] = array_flip($mapping['sourceToTargetKeyColumns']);
}
$mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) ? (bool) $mapping['orphanRemoval'] : false;
$mapping['isCascadeRemove'] = $mapping['orphanRemoval'] ? true : $mapping['isCascadeRemove'];
if (isset($mapping['id']) && $mapping['id'] === true && !$mapping['isOwningSide']) {
throw MappingException::illegalInverseIdentifierAssocation($this->name, $mapping['fieldName']);
}
//TODO: if orphanRemoval, cascade=remove is implicit!
$mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) ?
(bool) $mapping['orphanRemoval'] : false;
return $mapping;
}
@@ -937,16 +818,17 @@ class ClassMetadataInfo implements ClassMetadata
if ( ! isset($mapping['mappedBy'])) {
throw MappingException::oneToManyRequiresMappedBy($mapping['fieldName']);
}
$mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) ? (bool) $mapping['orphanRemoval'] : false;
$mapping['isCascadeRemove'] = $mapping['orphanRemoval'] ? true : $mapping['isCascadeRemove'];
//TODO: if orphanRemoval, cascade=remove is implicit!
$mapping['orphanRemoval'] = isset($mapping['orphanRemoval']) ?
(bool) $mapping['orphanRemoval'] : false;
if (isset($mapping['orderBy'])) {
if ( ! is_array($mapping['orderBy'])) {
throw new \InvalidArgumentException("'orderBy' is expected to be an array, not ".gettype($mapping['orderBy']));
}
}
return $mapping;
}
@@ -964,7 +846,7 @@ class ClassMetadataInfo implements ClassMetadata
} else {
$targetShortName = strtolower($mapping['targetEntity']);
}
// owning side MUST have a join table
if ( ! isset($mapping['joinTable']['name'])) {
$mapping['joinTable']['name'] = $sourceShortName .'_' . $targetShortName;
@@ -1070,16 +952,6 @@ class ClassMetadataInfo implements ClassMetadata
$this->isIdentifierComposite = (count($this->identifier) > 1);
}
/**
* Gets the mapped identifier field of this class.
*
* @return string $identifier
*/
public function getIdentifier()
{
return $this->identifier;
}
/**
* Checks whether the class has a (mapped) field with a certain name.
*
@@ -1115,23 +987,15 @@ class ClassMetadataInfo implements ClassMetadata
*/
public function getIdentifierColumnNames()
{
$columnNames = array();
foreach ($this->identifier as $idProperty) {
if (isset($this->fieldMappings[$idProperty])) {
$columnNames[] = $this->fieldMappings[$idProperty]['columnName'];
continue;
if ($this->isIdentifierComposite) {
$columnNames = array();
foreach ($this->identifier as $idField) {
$columnNames[] = $this->fieldMappings[$idField]['columnName'];
}
// 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;
} else {
return array($this->fieldMappings[$this->identifier[0]]['columnName']);
}
return $columnNames;
}
/**
@@ -1238,7 +1102,7 @@ class ClassMetadataInfo implements ClassMetadata
* Gets the type of a field.
*
* @param string $fieldName
* @return \Doctrine\DBAL\Types\Type
* @return Doctrine\DBAL\Types\Type
*/
public function getTypeOfField($fieldName)
{
@@ -1249,7 +1113,7 @@ class ClassMetadataInfo implements ClassMetadata
/**
* Gets the type of a column.
*
* @return \Doctrine\DBAL\Types\Type
* @return Doctrine\DBAL\Types\Type
*/
public function getTypeOfColumn($columnName)
{
@@ -1414,7 +1278,8 @@ class ClassMetadataInfo implements ClassMetadata
* Adds an association mapping without completing/validating it.
* This is mainly used to add inherited association mappings to derived classes.
*
* @param array $mapping
* @param AssociationMapping $mapping
* @param string $owningClassName The name of the class that defined this mapping.
*/
public function addInheritedAssociationMapping(array $mapping/*, $owningClassName = null*/)
{
@@ -1430,6 +1295,7 @@ class ClassMetadataInfo implements ClassMetadata
* This is mainly used to add inherited field mappings to derived classes.
*
* @param array $mapping
* @todo Rename: addInheritedFieldMapping
*/
public function addInheritedFieldMapping(array $fieldMapping)
{
@@ -1438,22 +1304,6 @@ class ClassMetadataInfo implements ClassMetadata
$this->fieldNames[$fieldMapping['columnName']] = $fieldMapping['fieldName'];
}
/**
* INTERNAL:
* Adds a named query to this class.
*
* @throws MappingException
* @param array $queryMapping
*/
public function addNamedQuery(array $queryMapping)
{
if (isset($this->namedQueries[$queryMapping['name']])) {
throw MappingException::duplicateQueryMapping($this->name, $queryMapping['name']);
}
$query = str_replace('__CLASS__', $this->name, $queryMapping['query']);
$this->namedQueries[$queryMapping['name']] = $query;
}
/**
* Adds a one-to-one mapping.
*
@@ -1627,13 +1477,11 @@ class ClassMetadataInfo implements ClassMetadata
public function setDiscriminatorMap(array $map)
{
foreach ($map as $value => $className) {
if (strlen($this->namespace) > 0 && strpos($className, '\\') === false) {
if (strpos($className, '\\') === false && strlen($this->namespace)) {
$className = $this->namespace . '\\' . $className;
}
$className = ltrim($className, '\\');
$this->discriminatorMap[$value] = $className;
if ($this->name == $className) {
$this->discriminatorValue = $value;
} else {
@@ -1647,17 +1495,6 @@ class ClassMetadataInfo implements ClassMetadata
}
}
/**
* Checks whether the class has a named query with the given query name.
*
* @param string $fieldName
* @return boolean
*/
public function hasNamedQuery($queryName)
{
return isset($this->namedQueries[$queryName]);
}
/**
* Checks whether the class has a mapped association with the given field name.
*
@@ -1695,74 +1532,6 @@ class ClassMetadataInfo implements ClassMetadata
! ($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])
);
}
/**
* Return the single association join column (if any).
*
* @param string $fieldName
* @return string
*/
public function getSingleAssociationJoinColumnName($fieldName)
{
if (!$this->isAssociationWithSingleJoinColumn($fieldName)) {
throw MappingException::noSingleAssociationJoinColumnFound($this->name, $fieldName);
}
return $this->associationMappings[$fieldName]['joinColumns'][0]['name'];
}
/**
* Return the single association referenced join column name (if any).
*
* @param string $fieldName
* @return string
*/
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
*/
public function getFieldForColumn($columnName)
{
if (isset($this->fieldNames[$columnName])) {
return $this->fieldNames[$columnName];
} else {
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.
*
@@ -1834,150 +1603,4 @@ class ClassMetadataInfo implements ClassMetadata
{
$this->versionField = $versionField;
}
/**
* Mark this class as read only, no change tracking is applied to it.
*
* @return void
*/
public function markReadOnly()
{
$this->isReadOnly = true;
}
/**
* A numerically indexed list of field names of this persistent class.
*
* This array includes identifier fields if present on this class.
*
* @return array
*/
public function getFieldNames()
{
return array_keys($this->fieldMappings);
}
/**
* A numerically indexed list of association names of this persistent class.
*
* This array includes identifier associations if present on this class.
*
* @return array
*/
public function getAssociationNames()
{
return array_keys($this->associationMappings);
}
/**
* Returns the target class name of the given association.
*
* @param string $assocName
* @return string
*/
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'];
}
/**
* Get fully-qualified class name of this persistent class.
*
* @return string
*/
public function getName()
{
return $this->name;
}
/**
* Gets the (possibly quoted) identifier column names for safe use in an SQL statement.
*
* @param AbstractPlatform $platform
* @return array
*/
public function getQuotedIdentifierColumnNames($platform)
{
$quotedColumnNames = array();
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) {
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.
*
* @param string $field
* @param 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.
*
* @param 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.
*
* @param AbstractPlatform $platform
* @return string
*/
public function getQuotedJoinTableName(array $assoc, $platform)
{
return isset($assoc['joinTable']['quoted'])
? $platform->quoteIdentifier($assoc['joinTable']['name'])
: $assoc['joinTable']['name'];
}
public function isAssociationInverseSide($fieldName)
{
return isset($this->associationMappings[$fieldName]) && !$this->associationMappings[$fieldName]['isOwningSide'];
}
public function getAssociationMappedByTargetField($fieldName)
{
return $this->associationMappings[$fieldName]['mappedBy'];
}
}
}
@@ -21,10 +21,11 @@ namespace Doctrine\ORM\Mapping\Driver;
use Doctrine\Common\Cache\ArrayCache,
Doctrine\Common\Annotations\AnnotationReader,
Doctrine\Common\Annotations\AnnotationRegistry,
Doctrine\ORM\Mapping\ClassMetadataInfo,
Doctrine\ORM\Mapping\MappingException;
require __DIR__ . '/DoctrineAnnotations.php';
/**
* The AnnotationDriver reads the mapping metadata from docblock annotations.
*
@@ -41,7 +42,7 @@ class AnnotationDriver implements Driver
*
* @var AnnotationReader
*/
protected $_reader;
private $_reader;
/**
* The paths where to look for mapping files.
@@ -61,13 +62,13 @@ class AnnotationDriver implements Driver
* @param array
*/
protected $_classNames;
/**
* Initializes a new AnnotationDriver that uses the given AnnotationReader for reading
* docblock annotations.
*
*
* @param AnnotationReader $reader The AnnotationReader to use, duck-typed.
* @param string|array $paths One or multiple paths where mapping classes can be found.
* @param string|array $paths One or multiple paths where mapping classes can be found.
*/
public function __construct($reader, $paths = null)
{
@@ -76,7 +77,7 @@ class AnnotationDriver implements Driver
$this->addPaths((array) $paths);
}
}
/**
* Append lookup paths to metadata driver.
*
@@ -127,21 +128,10 @@ class AnnotationDriver implements Driver
$classAnnotations = $this->_reader->getClassAnnotations($class);
// Compatibility with Doctrine Common 3.x
if ($classAnnotations && is_int(key($classAnnotations))) {
foreach ($classAnnotations as $annot) {
$classAnnotations[get_class($annot)] = $annot;
}
}
// Evaluate Entity annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\Entity'])) {
$entityAnnot = $classAnnotations['Doctrine\ORM\Mapping\Entity'];
$metadata->setCustomRepositoryClass($entityAnnot->repositoryClass);
if ($entityAnnot->readOnly) {
$metadata->markReadOnly();
}
} else if (isset($classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'])) {
$metadata->isMappedSuperclass = true;
} else {
@@ -175,18 +165,6 @@ class AnnotationDriver implements Driver
$metadata->setPrimaryTable($primaryTable);
}
// Evaluate NamedQueries annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\NamedQueries'])) {
$namedQueriesAnnot = $classAnnotations['Doctrine\ORM\Mapping\NamedQueries'];
foreach ($namedQueriesAnnot->value as $namedQuery) {
$metadata->addNamedQuery(array(
'name' => $namedQuery->name,
'query' => $namedQuery->query
));
}
}
// Evaluate InheritanceType annotation
if (isset($classAnnotations['Doctrine\ORM\Mapping\InheritanceType'])) {
$inheritanceTypeAnnot = $classAnnotations['Doctrine\ORM\Mapping\InheritanceType'];
@@ -310,10 +288,6 @@ class AnnotationDriver implements Driver
throw MappingException::tableIdGeneratorNotImplemented($className);
}
} else if ($oneToOneAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OneToOne')) {
if ($idAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
$mapping['id'] = true;
}
$mapping['targetEntity'] = $oneToOneAnnot->targetEntity;
$mapping['joinColumns'] = $joinColumns;
$mapping['mappedBy'] = $oneToOneAnnot->mappedBy;
@@ -326,7 +300,6 @@ class AnnotationDriver implements Driver
$mapping['mappedBy'] = $oneToManyAnnot->mappedBy;
$mapping['targetEntity'] = $oneToManyAnnot->targetEntity;
$mapping['cascade'] = $oneToManyAnnot->cascade;
$mapping['indexBy'] = $oneToManyAnnot->indexBy;
$mapping['orphanRemoval'] = $oneToManyAnnot->orphanRemoval;
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToManyAnnot->fetch);
@@ -336,10 +309,6 @@ class AnnotationDriver implements Driver
$metadata->mapOneToMany($mapping);
} else if ($manyToOneAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToOne')) {
if ($idAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
$mapping['id'] = true;
}
$mapping['joinColumns'] = $joinColumns;
$mapping['cascade'] = $manyToOneAnnot->cascade;
$mapping['inversedBy'] = $manyToOneAnnot->inversedBy;
@@ -385,7 +354,6 @@ class AnnotationDriver implements Driver
$mapping['mappedBy'] = $manyToManyAnnot->mappedBy;
$mapping['inversedBy'] = $manyToManyAnnot->inversedBy;
$mapping['cascade'] = $manyToManyAnnot->cascade;
$mapping['indexBy'] = $manyToManyAnnot->indexBy;
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToManyAnnot->fetch);
if ($orderByAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
@@ -403,13 +371,6 @@ class AnnotationDriver implements Driver
if ($method->isPublic() && $method->getDeclaringClass()->getName() == $class->name) {
$annotations = $this->_reader->getMethodAnnotations($method);
// Compatibility with Doctrine Common 3.x
if ($annotations && is_int(key($annotations))) {
foreach ($annotations as $annot) {
$annotations[get_class($annot)] = $annot;
}
}
if (isset($annotations['Doctrine\ORM\Mapping\PrePersist'])) {
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::prePersist);
}
@@ -455,20 +416,6 @@ class AnnotationDriver implements Driver
{
$classAnnotations = $this->_reader->getClassAnnotations(new \ReflectionClass($className));
// Compatibility with Doctrine Common 3.x
if ($classAnnotations && is_int(key($classAnnotations))) {
foreach ($classAnnotations as $annot) {
if ($annot instanceof \Doctrine\ORM\Mapping\Entity) {
return false;
}
if ($annot instanceof \Doctrine\ORM\Mapping\MappedSuperclass) {
return false;
}
}
return true;
}
return ! isset($classAnnotations['Doctrine\ORM\Mapping\Entity']) &&
! isset($classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass']);
}
@@ -494,20 +441,18 @@ class AnnotationDriver implements Driver
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
}
$iterator = new \RegexIterator(
new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($path, \FilesystemIterator::SKIP_DOTS),
\RecursiveIteratorIterator::LEAVES_ONLY
),
'/^.+\\' . $this->_fileExtension . '$/i',
\RecursiveRegexIterator::GET_MATCH
$iterator = new \RecursiveIteratorIterator(
new \RecursiveDirectoryIterator($path),
\RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($iterator as $file) {
$sourceFile = realpath($file[0]);
if (($fileName = $file->getBasename($this->_fileExtension)) == $file->getBasename()) {
continue;
}
$sourceFile = realpath($file->getPathName());
require_once $sourceFile;
$includedFiles[] = $sourceFile;
}
}
@@ -529,7 +474,7 @@ class AnnotationDriver implements Driver
/**
* Factory method for the Annotation Driver
*
*
* @param array|string $paths
* @param AnnotationReader $reader
* @return AnnotationDriver
@@ -55,24 +55,7 @@ class DatabaseDriver implements Driver
* @var array
*/
private $manyToManyTables = array();
/**
* @var array
*/
private $classNamesForTables = array();
/**
* @var array
*/
private $fieldNamesForColumns = array();
/**
* The namespace for the generated entities.
*
* @var string
*/
private $namespace;
/**
* Initializes a new AnnotationDriver that uses the given AnnotationReader for reading
* docblock annotations.
@@ -95,7 +78,7 @@ class DatabaseDriver implements Driver
{
$this->tables = $this->manyToManyTables = $this->classToTableNames = array();
foreach ($entityTables AS $table) {
$className = $this->getClassNameForTable($table->getName());
$className = Inflector::classify(strtolower($table->getName()));
$this->classToTableNames[$className] = $table->getName();
$this->tables[$table->getName()] = $table;
}
@@ -110,8 +93,6 @@ class DatabaseDriver implements Driver
return;
}
$tables = array();
foreach ($this->_sm->listTableNames() as $tableName) {
$tables[$tableName] = $this->_sm->listTableDetails($tableName);
}
@@ -139,7 +120,7 @@ class DatabaseDriver implements Driver
} else {
// lower-casing is necessary because of Oracle Uppercase Tablenames,
// assumption is lower-case + underscore separated.
$className = $this->getClassNameForTable($tableName);
$className = Inflector::classify(strtolower($tableName));
$this->tables[$tableName] = $table;
$this->classToTableNames[$className] = $tableName;
}
@@ -191,7 +172,7 @@ class DatabaseDriver implements Driver
continue;
}
$fieldMapping['fieldName'] = $this->getFieldNameForColumn($tableName, $column->getName(), false);
$fieldMapping['fieldName'] = Inflector::camelize(strtolower($column->getName()));
$fieldMapping['columnName'] = $column->getName();
$fieldMapping['type'] = strtolower((string) $column->getType());
@@ -245,10 +226,10 @@ class DatabaseDriver implements Driver
$localColumn = current($myFk->getColumns());
$associationMapping = array();
$associationMapping['fieldName'] = $this->getFieldNameForColumn($manyTable->getName(), current($otherFk->getColumns()), true);
$associationMapping['targetEntity'] = $this->getClassNameForTable($otherFk->getForeignTableName());
$associationMapping['fieldName'] = Inflector::camelize(str_replace('_id', '', strtolower(current($otherFk->getColumns()))));
$associationMapping['targetEntity'] = Inflector::classify(strtolower($otherFk->getForeignTableName()));
if (current($manyTable->getColumns())->getName() == $localColumn) {
$associationMapping['inversedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getColumns()), true);
$associationMapping['inversedBy'] = Inflector::camelize(str_replace('_id', '', strtolower(current($myFk->getColumns()))));
$associationMapping['joinTable'] = array(
'name' => strtolower($manyTable->getName()),
'joinColumns' => array(),
@@ -273,7 +254,7 @@ class DatabaseDriver implements Driver
);
}
} else {
$associationMapping['mappedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getColumns()), true);
$associationMapping['mappedBy'] = Inflector::camelize(str_replace('_id', '', strtolower(current($myFk->getColumns()))));
}
$metadata->mapManyToMany($associationMapping);
break;
@@ -288,8 +269,8 @@ class DatabaseDriver implements Driver
$localColumn = current($cols);
$associationMapping = array();
$associationMapping['fieldName'] = $this->getFieldNameForColumn($tableName, $localColumn, true);
$associationMapping['targetEntity'] = $this->getClassNameForTable($foreignTable);
$associationMapping['fieldName'] = Inflector::camelize(str_replace('_id', '', strtolower($localColumn)));
$associationMapping['targetEntity'] = Inflector::classify($foreignTable);
for ($i = 0; $i < count($cols); $i++) {
$associationMapping['joinColumns'][] = array(
@@ -322,78 +303,4 @@ class DatabaseDriver implements Driver
return array_keys($this->classToTableNames);
}
/**
* Set class name for a table.
*
* @param string $tableName
* @param string $className
* @return void
*/
public function setClassNameForTable($tableName, $className)
{
$this->classNamesForTables[$tableName] = $className;
}
/**
* Set 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;
}
/**
* Return 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 = str_replace('_id', '', $columnName);
}
return Inflector::camelize($columnName);
}
/**
* Set the namespace for the generated entities.
*
* @param string $namespace
* @return void
*/
public function setNamespace($namespace)
{
$this->namespace = $namespace;
}
}
}
@@ -1,5 +1,7 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -23,41 +25,23 @@ use Doctrine\Common\Annotations\Annotation;
/* Annotations */
/** @Annotation */
final class Entity extends Annotation {
public $repositoryClass;
public $readOnly = false;
}
/** @Annotation */
final class MappedSuperclass extends Annotation {}
/** @Annotation */
final class InheritanceType extends Annotation {}
/** @Annotation */
final class DiscriminatorColumn extends Annotation {
public $name;
public $fieldName; // field name used in non-object hydration (array/scalar)
public $type;
public $length;
}
/** @Annotation */
final class DiscriminatorMap extends Annotation {}
/** @Annotation */
final class Id extends Annotation {}
/** @Annotation */
final class GeneratedValue extends Annotation {
public $strategy = 'AUTO';
}
/** @Annotation */
final class Version extends Annotation {}
/** @Annotation */
final class JoinColumn extends Annotation {
public $name;
public $fieldName; // field name used in non-object hydration (array/scalar)
@@ -68,11 +52,7 @@ final class JoinColumn extends Annotation {
public $onUpdate;
public $columnDefinition;
}
/** @Annotation */
final class JoinColumns extends Annotation {}
/** @Annotation */
final class Column extends Annotation {
public $type = 'string';
public $length;
@@ -86,8 +66,6 @@ final class Column extends Annotation {
public $options = array();
public $columnDefinition;
}
/** @Annotation */
final class OneToOne extends Annotation {
public $targetEntity;
public $mappedBy;
@@ -96,111 +74,64 @@ final class OneToOne extends Annotation {
public $fetch = 'LAZY';
public $orphanRemoval = false;
}
/** @Annotation */
final class OneToMany extends Annotation {
public $mappedBy;
public $targetEntity;
public $cascade;
public $fetch = 'LAZY';
public $orphanRemoval = false;
public $indexBy;
}
/** @Annotation */
final class ManyToOne extends Annotation {
public $targetEntity;
public $cascade;
public $fetch = 'LAZY';
public $inversedBy;
}
/** @Annotation */
final class ManyToMany extends Annotation {
public $targetEntity;
public $mappedBy;
public $inversedBy;
public $cascade;
public $fetch = 'LAZY';
public $indexBy;
}
/** @Annotation */
final class ElementCollection extends Annotation {
public $tableName;
}
/** @Annotation */
final class Table extends Annotation {
public $name;
public $schema;
public $indexes;
public $uniqueConstraints;
}
/** @Annotation */
final class UniqueConstraint extends Annotation {
public $name;
public $columns;
}
/** @Annotation */
final class Index extends Annotation {
public $name;
public $columns;
}
/** @Annotation */
final class JoinTable extends Annotation {
public $name;
public $schema;
public $joinColumns = array();
public $inverseJoinColumns = array();
}
/** @Annotation */
final class SequenceGenerator extends Annotation {
public $sequenceName;
public $allocationSize = 1;
public $initialValue = 1;
}
/** @Annotation */
final class ChangeTrackingPolicy extends Annotation {}
/** @Annotation */
final class OrderBy extends Annotation {}
/** @Annotation */
final class NamedQueries extends Annotation {}
/** @Annotation */
final class NamedQuery extends Annotation {
public $name;
public $query;
}
/* Annotations for lifecycle callbacks */
/** @Annotation */
final class HasLifecycleCallbacks extends Annotation {}
/** @Annotation */
final class PrePersist extends Annotation {}
/** @Annotation */
final class PostPersist extends Annotation {}
/** @Annotation */
final class PreUpdate extends Annotation {}
/** @Annotation */
final class PostUpdate extends Annotation {}
/** @Annotation */
final class PreRemove extends Annotation {}
/** @Annotation */
final class PostRemove extends Annotation {}
/** @Annotation */
final class PostLoad extends Annotation {}
@@ -88,20 +88,15 @@ class DriverChain implements Driver
public function getAllClassNames()
{
$classNames = array();
$driverClasses = array();
foreach ($this->_drivers AS $namespace => $driver) {
$oid = spl_object_hash($driver);
if (!isset($driverClasses[$oid])) {
$driverClasses[$oid] = $driver->getAllClassNames();
}
foreach ($driverClasses[$oid] AS $className) {
$driverClasses = $driver->getAllClassNames();
foreach ($driverClasses AS $className) {
if (strpos($className, $namespace) === 0) {
$classNames[$className] = true;
$classNames[] = $className;
}
}
}
return array_keys($classNames);
return array_unique($classNames);
}
/**
+1 -40
View File
@@ -55,9 +55,6 @@ class XmlDriver extends AbstractFileDriver
$metadata->setCustomRepositoryClass(
isset($xmlRoot['repository-class']) ? (string)$xmlRoot['repository-class'] : null
);
if (isset($xmlRoot['read-only']) && $xmlRoot['read-only'] == "true") {
$metadata->markReadOnly();
}
} else if ($xmlRoot->getName() == 'mapped-superclass') {
$metadata->isMappedSuperclass = true;
} else {
@@ -72,21 +69,11 @@ class XmlDriver extends AbstractFileDriver
$metadata->setPrimaryTable($table);
// Evaluate named queries
if (isset($xmlRoot['named-queries'])) {
foreach ($xmlRoot->{'named-queries'}->{'named-query'} as $namedQueryElement) {
$metadata->addNamedQuery(array(
'name' => (string)$namedQueryElement['name'],
'query' => (string)$namedQueryElement['query']
));
}
}
/* not implemented specially anyway. use table = schema.table
if (isset($xmlRoot['schema'])) {
$metadata->table['schema'] = (string)$xmlRoot['schema'];
}*/
if (isset($xmlRoot['inheritance-type'])) {
$inheritanceType = (string)$xmlRoot['inheritance-type'];
$metadata->setInheritanceType(constant('Doctrine\ORM\Mapping\ClassMetadata::INHERITANCE_TYPE_' . $inheritanceType));
@@ -207,13 +194,7 @@ class XmlDriver extends AbstractFileDriver
}
// Evaluate <id ...> mappings
$associationIds = array();
foreach ($xmlRoot->id as $idElement) {
if ((bool)$idElement['association-key'] == true) {
$associationIds[(string)$idElement['name']] = true;
continue;
}
$mapping = array(
'id' => true,
'fieldName' => (string)$idElement['name'],
@@ -254,10 +235,6 @@ class XmlDriver extends AbstractFileDriver
'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']);
}
@@ -322,12 +299,6 @@ class XmlDriver extends AbstractFileDriver
$mapping['orderBy'] = $orderBy;
}
if (isset($oneToManyElement['index-by'])) {
$mapping['indexBy'] = (string)$oneToManyElement['index-by'];
} else if (isset($oneToManyElement->{'index-by'})) {
throw new \InvalidArgumentException("<index-by /> is not a valid tag");
}
$metadata->mapOneToMany($mapping);
}
}
@@ -340,10 +311,6 @@ class XmlDriver extends AbstractFileDriver
'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']);
}
@@ -431,12 +398,6 @@ class XmlDriver extends AbstractFileDriver
$mapping['orderBy'] = $orderBy;
}
if (isset($manyToManyElement['index-by'])) {
$mapping['indexBy'] = (string)$manyToManyElement['index-by'];
} else if (isset($manyToManyElement->{'index-by'})) {
throw new \InvalidArgumentException("<index-by /> is not a valid tag");
}
$metadata->mapManyToMany($mapping);
}
}
+4 -52
View File
@@ -49,9 +49,6 @@ class YamlDriver extends AbstractFileDriver
$metadata->setCustomRepositoryClass(
isset($element['repositoryClass']) ? $element['repositoryClass'] : null
);
if (isset($element['readOnly']) && $element['readOnly'] == true) {
$metadata->markReadOnly();
}
} else if ($element['type'] == 'mappedSuperclass') {
$metadata->isMappedSuperclass = true;
} else {
@@ -65,21 +62,6 @@ class YamlDriver extends AbstractFileDriver
}
$metadata->setPrimaryTable($table);
// Evaluate named queries
if (isset($element['namedQueries'])) {
foreach ($element['namedQueries'] as $name => $queryMapping) {
if (is_string($queryMapping)) {
$queryMapping = array('query' => $queryMapping);
}
if ( ! isset($queryMapping['name'])) {
$queryMapping['name'] = $name;
}
$metadata->addNamedQuery($queryMapping);
}
}
/* not implemented specially anyway. use table = schema.table
if (isset($element['schema'])) {
$metadata->table['schema'] = $element['schema'];
@@ -153,15 +135,9 @@ class YamlDriver extends AbstractFileDriver
}
}
$associationIds = array();
if (isset($element['id'])) {
// Evaluate identifier settings
foreach ($element['id'] as $name => $idElement) {
if (isset($idElement['associationKey']) && $idElement['associationKey'] == true) {
$associationIds[$name] = true;
continue;
}
if (!isset($idElement['type'])) {
throw MappingException::propertyTypeIsRequired($className, $name);
}
@@ -258,10 +234,6 @@ class YamlDriver extends AbstractFileDriver
'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']);
}
@@ -315,20 +287,16 @@ class YamlDriver extends AbstractFileDriver
$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['cascade'])) {
$mapping['cascade'] = $oneToManyElement['cascade'];
}
if (isset($oneToManyElement['indexBy'])) {
$mapping['indexBy'] = $oneToManyElement['indexBy'];
if (isset($oneToManyElement['orderBy'])) {
$mapping['orderBy'] = $oneToManyElement['orderBy'];
}
$metadata->mapOneToMany($mapping);
@@ -343,10 +311,6 @@ class YamlDriver extends AbstractFileDriver
'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']);
}
@@ -375,10 +339,6 @@ class YamlDriver extends AbstractFileDriver
$mapping['cascade'] = $manyToOneElement['cascade'];
}
if (isset($manyToOneElement['orphanRemoval'])) {
$mapping['orphanRemoval'] = (bool)$manyToOneElement['orphanRemoval'];
}
$metadata->mapManyToOne($mapping);
}
}
@@ -434,18 +394,10 @@ class YamlDriver extends AbstractFileDriver
$mapping['cascade'] = $manyToManyElement['cascade'];
}
if (isset($manyToManyElement['orphanRemoval'])) {
$mapping['orphanRemoval'] = (bool)$manyToManyElement['orphanRemoval'];
}
if (isset($manyToManyElement['orderBy'])) {
$mapping['orderBy'] = $manyToManyElement['orderBy'];
}
if (isset($manyToManyElement['indexBy'])) {
$mapping['indexBy'] = $manyToManyElement['indexBy'];
}
$metadata->mapManyToMany($mapping);
}
}
@@ -73,11 +73,6 @@ class MappingException extends \Doctrine\ORM\ORMException
return new self("No mapping found for field '$fieldName' on class '$className'.");
}
public static function queryNotFound($className, $queryName)
{
return new self("No query found named '$queryName' on class '$className'.");
}
public static function oneToManyRequiresMappedBy($fieldName)
{
return new self("OneToMany mapping on field '$fieldName' requires the 'mappedBy' attribute.");
@@ -165,10 +160,6 @@ class MappingException extends \Doctrine\ORM\ORMException
return new self('Property "'.$fieldName.'" in "'.$entity.'" was already declared, but it must be declared only once');
}
public static function duplicateQueryMapping($entity, $queryName) {
return new self('Query named "'.$queryName.'" in "'.$entity.'" was already declared, but it must be declared only once');
}
public static function singleIdNotAllowedOnCompositePrimaryKey($entity) {
return new self('Single id is not allowed on composite primary key in entity '.$entity);
}
@@ -240,57 +231,4 @@ class MappingException extends \Doctrine\ORM\ORMException
{
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 self
*/
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."'.");
}
public static function noSingleAssociationJoinColumnFound($className, $field)
{
return new self("'$className#$field' is not an association with a single join column.");
}
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.");
}
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'.");
}
public static function illegalInverseIdentifierAssocation($className, $field)
{
return new self("An inverse association is not allowed to be identifier in '$className#$field'.");
}
public static function illegalToManyIdentifierAssoaction($className, $field)
{
return new self("Many-to-many or one-to-many associations are not allowed to be identifier in '$className#$field'.");
}
public static function noInheritanceOnMappedSuperClass($className)
{
return new self("Its not supported to define inheritance information on a mapped superclass '" . $className . "'.");
}
public static function mappedClassNotPartOfDiscriminatorMap($className, $rootClassName)
{
return new self(
"Entity '" . $className . "' has to be part of the descriminator map of '" . $rootClassName . "' " .
"to be properly mapped in the inheritance hierachy. Alternatively you can make '".$className."' an abstract class " .
"to avoid this exception from occuring."
);
}
}
+1 -25
View File
@@ -34,25 +34,10 @@ class ORMException extends Exception
return new self("It's a requirement to specify a Metadata Driver and pass it ".
"to Doctrine\ORM\Configuration::setMetadataDriverImpl().");
}
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 ientity itself. You have to call EntityManager#persist() on the related entity " .
"and make sure it an identifier was generated before trying to persist '" . get_class($entity) . "'. In case " .
"of Post Insert ID Generation (such as MySQL Auto-Increment or PostgreSQL SERIAL) this means you have to call " .
"EntityManager#flush() between both persist operations."
);
}
public static function entityMissingAssignedId($entity)
{
return new self("Entity of type " . get_class($entity) . " is missing an assigned ID. " .
"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."
);
return new self("Entity of type " . get_class($entity) . " is missing an assigned ID.");
}
public static function unrecognizedField($field)
@@ -60,15 +45,6 @@ class ORMException extends Exception
return new self("Unrecognized field: $field");
}
/**
* @param string $className
* @param string $field
*/
public static function invalidOrientation($className, $field)
{
return new self("Invalid order by orientation specified for " . $className . "#" . $field);
}
public static function invalidFlushMode($mode)
{
return new self("'$mode' is an invalid flush mode.");
+41 -49
View File
@@ -59,14 +59,14 @@ final class PersistentCollection implements Collection
* The association mapping the collection belongs to.
* This is currently either a OneToManyMapping or a ManyToManyMapping.
*
* @var array
* @var Doctrine\ORM\Mapping\AssociationMapping
*/
private $association;
/**
* The EntityManager that manages the persistence of the collection.
*
* @var \Doctrine\ORM\EntityManager
* @var Doctrine\ORM\EntityManager
*/
private $em;
@@ -93,21 +93,21 @@ final class PersistentCollection implements Collection
/**
* Whether the collection has already been initialized.
*
*
* @var boolean
*/
private $initialized = true;
/**
* The wrapped Collection instance.
*
*
* @var Collection
*/
private $coll;
/**
* Creates a new persistent collection.
*
*
* @param EntityManager $em The EntityManager the collection will be associated with.
* @param ClassMetadata $class The class descriptor of the entity type of this collection.
* @param array The collection elements.
@@ -144,7 +144,7 @@ final class PersistentCollection implements Collection
{
return $this->owner;
}
public function getTypeClass()
{
return $this->typeClass;
@@ -154,7 +154,7 @@ final class PersistentCollection implements Collection
* 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.
*/
public function hydrateAdd($element)
@@ -172,7 +172,7 @@ final class PersistentCollection implements Collection
$this->owner);
}
}
/**
* INTERNAL:
* Sets a keyed element in the collection during hydration.
@@ -265,13 +265,13 @@ final class PersistentCollection implements Collection
/**
* INTERNAL: Gets the association mapping of the collection.
*
* @return \Doctrine\ORM\Mapping\AssociationMapping
* @return Doctrine\ORM\Mapping\AssociationMapping
*/
public function getMapping()
{
return $this->association;
}
/**
* Marks this collection as changed/dirty.
*/
@@ -306,17 +306,17 @@ final class PersistentCollection implements Collection
{
$this->isDirty = $dirty;
}
/**
* Sets the initialized flag of the collection, forcing it into that state.
*
*
* @param boolean $bool
*/
public function setInitialized($bool)
{
$this->initialized = $bool;
}
/**
* Checks whether this collection has been initialized.
*
@@ -377,7 +377,7 @@ final class PersistentCollection implements Collection
$this->em->getUnitOfWork()->getCollectionPersister($this->association)
->deleteRows($this, $element);
}*/
$this->initialize();
$removed = $this->coll->removeElement($element);
if ($removed) {
@@ -404,13 +404,23 @@ final class PersistentCollection implements Collection
*/
public function contains($element)
{
if (!$this->initialized && $this->association['fetch'] == Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY) {
return $this->coll->contains($element) ||
$this->em->getUnitOfWork()
->getCollectionPersister($this->association)
->contains($this, $element);
}
/* DRAFT
if ($this->initialized) {
return $this->coll->contains($element);
} else {
if ($element is MANAGED) {
if ($this->coll->contains($element)) {
return true;
}
$exists = check db for existence;
if ($exists) {
$this->coll->add($element);
}
return $exists;
}
return false;
}*/
$this->initialize();
return $this->coll->contains($element);
}
@@ -465,12 +475,6 @@ final class PersistentCollection implements Collection
*/
public function count()
{
if (!$this->initialized && $this->association['fetch'] == Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY) {
return $this->em->getUnitOfWork()
->getCollectionPersister($this->association)
->count($this) + ($this->isDirty ? $this->coll->count() : 0);
}
$this->initialize();
return $this->coll->count();
}
@@ -503,7 +507,7 @@ final class PersistentCollection implements Collection
$this->initialize();
return $this->coll->isEmpty();
}
/**
* {@inheritdoc}
*/
@@ -530,7 +534,7 @@ final class PersistentCollection implements Collection
$this->initialize();
return $this->coll->filter($p);
}
/**
* {@inheritdoc}
*/
@@ -548,7 +552,7 @@ final class PersistentCollection implements Collection
$this->initialize();
return $this->coll->partition($p);
}
/**
* {@inheritdoc}
*/
@@ -567,9 +571,6 @@ final class PersistentCollection implements Collection
return;
}
if ($this->association['type'] == ClassMetadata::ONE_TO_MANY && $this->association['orphanRemoval']) {
// 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->coll as $element) {
$this->em->getUnitOfWork()->scheduleOrphanRemoval($element);
}
@@ -582,7 +583,7 @@ final class PersistentCollection implements Collection
$this->takeSnapshot();
}
}
/**
* Called by PHP when this collection is serialized. Ensures that only the
* elements are properly serialized.
@@ -594,7 +595,7 @@ final class PersistentCollection implements Collection
{
return array('coll', 'initialized');
}
/* ArrayAccess implementation */
/**
@@ -632,12 +633,12 @@ final class PersistentCollection implements Collection
{
return $this->remove($offset);
}
public function key()
{
return $this->coll->key();
}
/**
* Gets the element of the collection at the current iterator position.
*/
@@ -645,7 +646,7 @@ final class PersistentCollection implements Collection
{
return $this->coll->current();
}
/**
* Moves the internal iterator position to the next element.
*/
@@ -653,7 +654,7 @@ final class PersistentCollection implements Collection
{
return $this->coll->next();
}
/**
* Retrieves the wrapped Collection instance.
*/
@@ -675,15 +676,6 @@ final class PersistentCollection implements Collection
*/
public function slice($offset, $length = null)
{
if ( ! $this->initialized &&
! $this->isDirty &&
$this->association['fetch'] == Mapping\ClassMetadataInfo::FETCH_EXTRA_LAZY) {
return $this->em->getUnitOfWork()
->getCollectionPersister($this->association)
->slice($this, $offset, $length);
}
$this->initialize();
return $this->coll->slice($offset, $length);
}
@@ -36,19 +36,19 @@ abstract class AbstractCollectionPersister
protected $_em;
/**
* @var \Doctrine\DBAL\Connection
* @var Doctrine\DBAL\Connection
*/
protected $_conn;
/**
* @var \Doctrine\ORM\UnitOfWork
* @var Doctrine\ORM\UnitOfWork
*/
protected $_uow;
/**
* Initializes a new instance of a class derived from AbstractCollectionPersister.
*
* @param \Doctrine\ORM\EntityManager $em
* @param Doctrine\ORM\EntityManager $em
*/
public function __construct(EntityManager $em)
{
@@ -65,11 +65,9 @@ abstract class AbstractCollectionPersister
public function delete(PersistentCollection $coll)
{
$mapping = $coll->getMapping();
if ( ! $mapping['isOwningSide']) {
return; // ignore inverse side
}
$sql = $this->_getDeleteSQL($coll);
$this->_conn->executeUpdate($sql, $this->_getDeleteSQLParameters($coll));
}
@@ -98,11 +96,9 @@ abstract class AbstractCollectionPersister
public function update(PersistentCollection $coll)
{
$mapping = $coll->getMapping();
if ( ! $mapping['isOwningSide']) {
return; // ignore inverse side
}
$this->deleteRows($coll);
//$this->updateRows($coll);
$this->insertRows($coll);
@@ -112,7 +108,6 @@ abstract class AbstractCollectionPersister
{
$deleteDiff = $coll->getDeleteDiff();
$sql = $this->_getDeleteRowSQL($coll);
foreach ($deleteDiff as $element) {
$this->_conn->executeUpdate($sql, $this->_getDeleteRowSQLParameters($coll, $element));
}
@@ -125,37 +120,11 @@ abstract class AbstractCollectionPersister
{
$insertDiff = $coll->getInsertDiff();
$sql = $this->_getInsertRowSQL($coll);
foreach ($insertDiff as $element) {
$this->_conn->executeUpdate($sql, $this->_getInsertRowSQLParameters($coll, $element));
}
}
public function count(PersistentCollection $coll)
{
throw new \BadMethodCallException("Counting the size of this persistent collection is not supported by this CollectionPersister.");
}
public function slice(PersistentCollection $coll, $offset, $length = null)
{
throw new \BadMethodCallException("Slicing elements is not supported by this CollectionPersister.");
}
public function contains(PersistentCollection $coll, $element)
{
throw new \BadMethodCallException("Checking for existance of an element is not supported by this CollectionPersister.");
}
public function containsKey(PersistentCollection $coll, $key)
{
throw new \BadMethodCallException("Checking for existance of a key is not supported by this CollectionPersister.");
}
public function get(PersistentCollection $coll, $index)
{
throw new \BadMethodCallException("Selecting a collection by index is not supported by this CollectionPersister.");
}
/**
* Gets the SQL statement used for deleting a row from the collection.
*
@@ -28,23 +28,34 @@ use Doctrine\ORM\Mapping\ClassMetadata,
* types in the hierarchy.
*
* @author Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @since 2.0
*/
abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
{
/**
* Map from column names to class metadata instances that declare the field the column is mapped to.
*
* @var array
*/
private $declaringClassMap = array();
/**
* Map from column names to class names that declare the field the association with join column is mapped to.
*
* @var array
*/
private $declaringJoinColumnMap = array();
/**
* {@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;
}
@@ -58,22 +69,62 @@ abstract class AbstractEntityInheritancePersister extends BasicEntityPersister
/**
* {@inheritdoc}
*/
protected function _getSelectColumnSQL($field, ClassMetadata $class, $alias = 'r')
protected function _processSQLResult(array $sqlResult)
{
$data = array();
$discrColumnName = $this->_platform->getSQLResultCasing($this->_class->discriminatorColumn['name']);
$entityName = $this->_class->discriminatorMap[$sqlResult[$discrColumnName]];
unset($sqlResult[$discrColumnName]);
foreach ($sqlResult as $column => $value) {
$realColumnName = $this->_resultColumnNames[$column];
if (isset($this->declaringClassMap[$column])) {
$class = $this->declaringClassMap[$column];
if ($class->name == $entityName || is_subclass_of($entityName, $class->name)) {
$field = $class->fieldNames[$realColumnName];
if (isset($data[$field])) {
$data[$realColumnName] = $value;
} else {
$data[$field] = Type::getType($class->fieldMappings[$field]['type'])
->convertToPHPValue($value, $this->_platform);
}
}
} else if (isset($this->declaringJoinColumnMap[$column])) {
if ($this->declaringJoinColumnMap[$column] == $entityName || is_subclass_of($entityName, $this->declaringJoinColumnMap[$column])) {
$data[$realColumnName] = $value;
}
} else {
$data[$realColumnName] = $value;
}
}
return array($entityName, $data);
}
/**
* {@inheritdoc}
*/
protected function _getSelectColumnSQL($field, ClassMetadata $class)
{
$columnName = $class->columnNames[$field];
$sql = $this->_getSQLTableAlias($class->name, $alias == 'r' ? '' : $alias) . '.' . $class->getQuotedColumnName($field, $this->_platform);
$sql = $this->_getSQLTableAlias($class->name) . '.' . $class->getQuotedColumnName($field, $this->_platform);
$columnAlias = $this->_platform->getSQLResultCasing($columnName . $this->_sqlAliasCounter++);
$this->_rsm->addFieldResult($alias, $columnAlias, $field, $class->name);
if ( ! isset($this->_resultColumnNames[$columnAlias])) {
$this->_resultColumnNames[$columnAlias] = $columnName;
$this->declaringClassMap[$columnAlias] = $class;
}
return $sql . ' AS ' . $columnAlias;
return "$sql AS $columnAlias";
}
protected function getSelectJoinColumnSQL($tableAlias, $joinColumnName, $className)
{
$columnAlias = $joinColumnName . $this->_sqlAliasCounter++;
$resultColumnName = $this->_platform->getSQLResultCasing($columnAlias);
$this->_rsm->addMetaResult('r', $resultColumnName, $joinColumnName);
if ( ! isset($this->_resultColumnNames[$resultColumnName])) {
$this->_resultColumnNames[$resultColumnName] = $joinColumnName;
$this->declaringJoinColumnMap[$resultColumnName] = $className;
}
return $tableAlias . '.' . $joinColumnName . ' AS ' . $columnAlias;
return $tableAlias . ".$joinColumnName AS $columnAlias";
}
}
File diff suppressed because it is too large Load Diff
@@ -20,17 +20,13 @@
namespace Doctrine\ORM\Persisters;
use Doctrine\ORM\ORMException,
Doctrine\ORM\Mapping\ClassMetadata,
Doctrine\DBAL\LockMode,
Doctrine\DBAL\Types\Type,
Doctrine\ORM\Query\ResultSetMapping;
Doctrine\ORM\Mapping\ClassMetadata;
/**
* The joined subclass persister maps a single entity instance to several tables in the
* database as it is defined by the <tt>Class Table Inheritance</tt> strategy.
*
* @author Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @since 2.0
* @see http://martinfowler.com/eaaCatalog/classTableInheritance.html
*/
@@ -67,7 +63,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
* This function finds the ClassMetadata instance in an inheritance hierarchy
* that is responsible for enabling versioning.
*
* @return \Doctrine\ORM\Mapping\ClassMetadata
* @return Doctrine\ORM\Mapping\ClassMetadata
*/
private function _getVersionedClassMetadata()
{
@@ -144,11 +140,9 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
// Execute insert on root table
$paramIndex = 1;
foreach ($insertData[$rootTableName] as $columnName => $value) {
$rootTableStmt->bindValue($paramIndex++, $value, $this->_columnTypes[$columnName]);
}
$rootTableStmt->execute();
if ($isPostInsertId) {
@@ -163,17 +157,12 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
foreach ($subTableStmts as $tableName => $stmt) {
$data = isset($insertData[$tableName]) ? $insertData[$tableName] : array();
$paramIndex = 1;
foreach ((array) $id as $idName => $idVal) {
$type = isset($this->_columnTypes[$idName]) ? $this->_columnTypes[$idName] : Type::STRING;
$stmt->bindValue($paramIndex++, $idVal, $type);
foreach ((array) $id as $idVal) {
$stmt->bindValue($paramIndex++, $idVal);
}
foreach ($data as $columnName => $value) {
$stmt->bindValue($paramIndex++, $value, $this->_columnTypes[$columnName]);
}
$stmt->execute();
}
}
@@ -199,7 +188,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
{
$updateData = $this->_prepareUpdateData($entity);
if (($isVersioned = $this->_class->isVersioned) != false) {
if ($isVersioned = $this->_class->isVersioned) {
$versionedClass = $this->_getVersionedClassMetadata();
$versionedTable = $versionedClass->table['name'];
}
@@ -208,7 +197,6 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
foreach ($updateData as $tableName => $data) {
$this->_updateTable($entity, $this->_quotedTableMap[$tableName], $data, $isVersioned && $versionedTable == $tableName);
}
// Make sure the table with the version column is updated even if no columns on that
// table were affected.
if ($isVersioned && ! isset($updateData[$versionedTable])) {
@@ -238,7 +226,6 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
} else {
// Delete from all tables individually, starting from this class' table up to the root table.
$this->_conn->delete($this->_class->getQuotedTableName($this->_platform), $id);
foreach ($this->_class->parentClasses as $parentClass) {
$this->_conn->delete($this->_em->getClassMetadata($parentClass)->getQuotedTableName($this->_platform), $id);
}
@@ -248,17 +235,13 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
/**
* {@inheritdoc}
*/
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null, $lockMode = 0, $limit = null, $offset = null, array $orderBy = null)
protected function _getSelectEntitiesSQL(array $criteria, $assoc = null, $lockMode = 0)
{
$idColumns = $this->_class->getIdentifierColumnNames();
$baseTableAlias = $this->_getSQLTableAlias($this->_class->name);
// Create the column list fragment only once
if ($this->_selectColumnListSql === null) {
$this->_rsm = new ResultSetMapping();
$this->_rsm->addEntityResult($this->_class->name, 'r');
// Add regular columns
$columnList = '';
foreach ($this->_class->fieldMappings as $fieldName => $mapping) {
@@ -294,8 +277,7 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
}
$resultColumnName = $this->_platform->getSQLResultCasing($discrColumn);
$this->_rsm->setDiscriminatorColumn('r', $resultColumnName);
$this->_rsm->addMetaResult('r', $resultColumnName, $discrColumn);
$this->_resultColumnNames[$resultColumnName] = $discrColumn;
}
// INNER JOIN parent tables
@@ -353,25 +335,19 @@ class JoinedSubclassPersister extends AbstractEntityInheritancePersister
$conditionSql = $this->_getSelectConditionSQL($criteria, $assoc);
$orderBy = ($assoc !== null && isset($assoc['orderBy'])) ? $assoc['orderBy'] : $orderBy;
$orderBySql = $orderBy ? $this->_getOrderBySQL($orderBy, $baseTableAlias) : '';
$orderBySql = '';
if ($assoc != null && isset($assoc['orderBy'])) {
$orderBySql = $this->_getCollectionOrderBySQL($assoc['orderBy'], $baseTableAlias);
}
if ($this->_selectColumnListSql === null) {
$this->_selectColumnListSql = $columnList;
}
$lockSql = '';
if ($lockMode == LockMode::PESSIMISTIC_READ) {
$lockSql = ' ' . $this->_platform->getReadLockSql();
} else if ($lockMode == LockMode::PESSIMISTIC_WRITE) {
$lockSql = ' ' . $this->_platform->getWriteLockSql();
}
return $this->_platform->modifyLimitQuery('SELECT ' . $this->_selectColumnListSql
return 'SELECT ' . $this->_selectColumnListSql
. ' FROM ' . $this->_class->getQuotedTableName($this->_platform) . ' ' . $baseTableAlias
. $joinSql
. ($conditionSql != '' ? ' WHERE ' . $conditionSql : '') . $orderBySql, $limit, $offset)
. $lockSql;
. ($conditionSql != '' ? ' WHERE ' . $conditionSql : '') . $orderBySql;
}
/**
@@ -21,8 +21,7 @@
namespace Doctrine\ORM\Persisters;
use Doctrine\ORM\PersistentCollection,
Doctrine\ORM\UnitOfWork;
use Doctrine\ORM\PersistentCollection;
/**
* Persister for many-to-many collections.
@@ -39,10 +38,9 @@ class ManyToManyPersister extends AbstractCollectionPersister
*/
protected function _getDeleteRowSQL(PersistentCollection $coll)
{
$mapping = $coll->getMapping();
$mapping = $coll->getMapping();
$joinTable = $mapping['joinTable'];
$columns = $mapping['joinTableColumns'];
$columns = $mapping['joinTableColumns'];
return 'DELETE FROM ' . $joinTable['name'] . ' WHERE ' . implode(' = ? AND ', $columns) . ' = ?';
}
@@ -119,21 +117,13 @@ class ManyToManyPersister extends AbstractCollectionPersister
foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
if (isset($mapping['relationToSourceKeyColumns'][$joinTableColumn])) {
if ($isComposite) {
if ($class1->containsForeignIdentifier) {
$params[] = $identifier1[$class1->getFieldForColumn($mapping['relationToSourceKeyColumns'][$joinTableColumn])];
} else {
$params[] = $identifier1[$class1->fieldNames[$mapping['relationToSourceKeyColumns'][$joinTableColumn]]];
}
$params[] = $identifier1[$class1->fieldNames[$mapping['relationToSourceKeyColumns'][$joinTableColumn]]];
} else {
$params[] = array_pop($identifier1);
}
} else {
if ($isComposite) {
if ($class2->containsForeignIdentifier) {
$params[] = $identifier2[$class2->getFieldForColumn($mapping['relationToTargetKeyColumns'][$joinTableColumn])];
} else {
$params[] = $identifier2[$class2->fieldNames[$mapping['relationToTargetKeyColumns'][$joinTableColumn]]];
}
$params[] = $identifier2[$class2->fieldNames[$mapping['relationToTargetKeyColumns'][$joinTableColumn]]];
} else {
$params[] = array_pop($identifier2);
}
@@ -183,119 +173,4 @@ class ManyToManyPersister extends AbstractCollectionPersister
return $params;
}
/**
* {@inheritdoc}
*/
public function count(PersistentCollection $coll)
{
$params = array();
$mapping = $coll->getMapping();
$class = $this->_em->getClassMetadata($mapping['sourceEntity']);
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($coll->getOwner());
if ($mapping['isOwningSide']) {
$joinTable = $mapping['joinTable'];
$joinColumns = $mapping['relationToSourceKeyColumns'];
} else {
$mapping = $this->_em->getClassMetadata($mapping['targetEntity'])->associationMappings[$mapping['mappedBy']];
$joinTable = $mapping['joinTable'];
$joinColumns = $mapping['relationToTargetKeyColumns'];
}
$whereClause = '';
foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
if (isset($joinColumns[$joinTableColumn])) {
if ($whereClause !== '') {
$whereClause .= ' AND ';
}
$whereClause .= "$joinTableColumn = ?";
if ($class->containsForeignIdentifier) {
$params[] = $id[$class->getFieldForColumn($joinColumns[$joinTableColumn])];
} else {
$params[] = $id[$class->fieldNames[$joinColumns[$joinTableColumn]]];
}
}
}
$sql = 'SELECT count(*) FROM ' . $joinTable['name'] . ' WHERE ' . $whereClause;
return $this->_conn->fetchColumn($sql, $params);
}
/**
* @param PersistentCollection $coll
* @param int $offset
* @param int $length
* @return array
*/
public function slice(PersistentCollection $coll, $offset, $length = null)
{
$mapping = $coll->getMapping();
return $this->_em->getUnitOfWork()
->getEntityPersister($mapping['targetEntity'])
->getManyToManyCollection($mapping, $coll->getOwner(), $offset, $length);
}
/**
* @param PersistentCollection $coll
* @param object $element
*/
public function contains(PersistentCollection $coll, $element)
{
$uow = $this->_em->getUnitOfWork();
// shortcut for new entities
if ($uow->getEntityState($element, UnitOfWork::STATE_NEW) == UnitOfWork::STATE_NEW) {
return false;
}
$params = array();
$mapping = $coll->getMapping();
if (!$mapping['isOwningSide']) {
$sourceClass = $this->_em->getClassMetadata($mapping['targetEntity']);
$targetClass = $this->_em->getClassMetadata($mapping['sourceEntity']);
$sourceId = $uow->getEntityIdentifier($element);
$targetId = $uow->getEntityIdentifier($coll->getOwner());
$mapping = $sourceClass->associationMappings[$mapping['mappedBy']];
} else {
$sourceClass = $this->_em->getClassMetadata($mapping['sourceEntity']);
$targetClass = $this->_em->getClassMetadata($mapping['targetEntity']);
$sourceId = $uow->getEntityIdentifier($coll->getOwner());
$targetId = $uow->getEntityIdentifier($element);
}
$joinTable = $mapping['joinTable'];
$whereClause = '';
foreach ($mapping['joinTableColumns'] as $joinTableColumn) {
if (isset($mapping['relationToTargetKeyColumns'][$joinTableColumn])) {
if ($whereClause !== '') {
$whereClause .= ' AND ';
}
$whereClause .= "$joinTableColumn = ?";
if ($targetClass->containsForeignIdentifier) {
$params[] = $targetId[$targetClass->getFieldForColumn($mapping['relationToTargetKeyColumns'][$joinTableColumn])];
} else {
$params[] = $targetId[$targetClass->fieldNames[$mapping['relationToTargetKeyColumns'][$joinTableColumn]]];
}
} else if (isset($mapping['relationToSourceKeyColumns'][$joinTableColumn])) {
if ($whereClause !== '') {
$whereClause .= ' AND ';
}
$whereClause .= "$joinTableColumn = ?";
if ($sourceClass->containsForeignIdentifier) {
$params[] = $sourceId[$sourceClass->getFieldForColumn($mapping['relationToSourceKeyColumns'][$joinTableColumn])];
} else {
$params[] = $sourceId[$sourceClass->fieldNames[$mapping['relationToSourceKeyColumns'][$joinTableColumn]]];
}
}
}
$sql = 'SELECT 1 FROM ' . $joinTable['name'] . ' WHERE ' . $whereClause;
return (bool)$this->_conn->fetchColumn($sql, $params);
}
}
@@ -21,8 +21,7 @@
namespace Doctrine\ORM\Persisters;
use Doctrine\ORM\PersistentCollection,
Doctrine\ORM\UnitOfWork;
use Doctrine\ORM\PersistentCollection;
/**
* Persister for one-to-many collections.
@@ -117,69 +116,4 @@ class OneToManyPersister extends AbstractCollectionPersister
*/
protected function _getDeleteRowSQLParameters(PersistentCollection $coll, $element)
{}
/**
* {@inheritdoc}
*/
public function count(PersistentCollection $coll)
{
$mapping = $coll->getMapping();
$targetClass = $this->_em->getClassMetadata($mapping['targetEntity']);
$sourceClass = $this->_em->getClassMetadata($mapping['sourceEntity']);
$params = array();
$id = $this->_em->getUnitOfWork()->getEntityIdentifier($coll->getOwner());
$where = '';
foreach ($targetClass->associationMappings[$mapping['mappedBy']]['joinColumns'] AS $joinColumn) {
if ($where != '') {
$where .= ' AND ';
}
$where .= $joinColumn['name'] . " = ?";
if ($targetClass->containsForeignIdentifier) {
$params[] = $id[$sourceClass->getFieldForColumn($joinColumn['referencedColumnName'])];
} else {
$params[] = $id[$sourceClass->fieldNames[$joinColumn['referencedColumnName']]];
}
}
$sql = "SELECT count(*) FROM " . $targetClass->getQuotedTableName($this->_conn->getDatabasePlatform()) . " WHERE " . $where;
return $this->_conn->fetchColumn($sql, $params);
}
/**
* @param PersistentCollection $coll
* @param int $offset
* @param int $length
* @return \Doctrine\Common\Collections\ArrayCollection
*/
public function slice(PersistentCollection $coll, $offset, $length = null)
{
$mapping = $coll->getMapping();
return $this->_em->getUnitOfWork()
->getEntityPersister($mapping['targetEntity'])
->getOneToManyCollection($mapping, $coll->getOwner(), $offset, $length);
}
/**
* @param PersistentCollection $coll
* @param object $element
*/
public function contains(PersistentCollection $coll, $element)
{
$mapping = $coll->getMapping();
$uow = $this->_em->getUnitOfWork();
// shortcut for new entities
if ($uow->getEntityState($element, UnitOfWork::STATE_NEW) == UnitOfWork::STATE_NEW) {
return false;
}
// only works with single id identifier entities. Will throw an exception in Entity Persisters
// if that is not the case for the 'mappedBy' field.
$id = current( $uow->getEntityIdentifier($coll->getOwner()) );
return $uow->getEntityPersister($mapping['targetEntity'])
->exists($element, array($mapping['mappedBy'] => $id));
}
}
}
@@ -26,7 +26,6 @@ use Doctrine\ORM\Mapping\ClassMetadata;
* SINGLE_TABLE strategy.
*
* @author Roman Borschel <roman@code-factory.org>
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @since 2.0
* @link http://martinfowler.com/eaaCatalog/singleTableInheritance.html
*/
@@ -41,10 +40,6 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
/** {@inheritdoc} */
protected function _getSelectColumnListSQL()
{
if ($this->_selectColumnListSql !== null) {
return $this->_selectColumnListSql;
}
$columnList = parent::_getSelectColumnListSQL();
// Append discriminator column
@@ -53,8 +48,7 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
$rootClass = $this->_em->getClassMetadata($this->_class->rootEntityName);
$tableAlias = $this->_getSQLTableAlias($rootClass->name);
$resultColumnName = $this->_platform->getSQLResultCasing($discrColumn);
$this->_rsm->setDiscriminatorColumn('r', $resultColumnName);
$this->_rsm->addMetaResult('r', $resultColumnName, $discrColumn);
$this->_resultColumnNames[$resultColumnName] = $discrColumn;
// Append subclass columns
foreach ($this->_class->subClasses as $subClassName) {
@@ -78,8 +72,7 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
}
}
$this->_selectColumnListSql = $columnList;
return $this->_selectColumnListSql;
return $columnList;
}
/** {@inheritdoc} */
@@ -93,9 +86,9 @@ class SingleTablePersister extends AbstractEntityInheritancePersister
}
/** {@inheritdoc} */
protected function _getSQLTableAlias($className, $assocName = '')
protected function _getSQLTableAlias($className)
{
return parent::_getSQLTableAlias($this->_class->rootEntityName, $assocName);
return parent::_getSQLTableAlias($this->_class->rootEntityName);
}
/** {@inheritdoc} */
+5 -7
View File
@@ -165,16 +165,14 @@ class ProxyFactory
{
$methods = '';
$methodNames = array();
foreach ($class->reflClass->getMethods() as $method) {
/* @var $method ReflectionMethod */
if ($method->isConstructor() || in_array(strtolower($method->getName()), array("__sleep", "__clone")) || isset($methodNames[$method->getName()])) {
if ($method->isConstructor() || in_array(strtolower($method->getName()), array("__sleep", "__clone"))) {
continue;
}
$methodNames[$method->getName()] = true;
if ($method->isPublic() && ! $method->isFinal() && ! $method->isStatic()) {
$methods .= "\n" . ' public function ';
$methods .= PHP_EOL . ' public function ';
if ($method->returnsReference()) {
$methods .= '&';
}
@@ -210,10 +208,10 @@ class ProxyFactory
}
$methods .= $parameterString . ')';
$methods .= "\n" . ' {' . "\n";
$methods .= ' $this->__load();' . "\n";
$methods .= PHP_EOL . ' {' . PHP_EOL;
$methods .= ' $this->__load();' . PHP_EOL;
$methods .= ' return parent::' . $method->getName() . '(' . $argumentString . ');';
$methods .= "\n" . ' }' . "\n";
$methods .= PHP_EOL . ' }' . PHP_EOL;
}
}
+56 -108
View File
@@ -44,28 +44,19 @@ final class Query extends AbstractQuery
* 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';
/**
* 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
*/
@@ -73,15 +64,15 @@ final class Query extends AbstractQuery
/**
* 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
* 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
@@ -89,7 +80,7 @@ final class Query extends AbstractQuery
const HINT_CUSTOM_TREE_WALKERS = 'doctrine.customTreeWalkers';
/**
* A string with a class name that implements \Doctrine\ORM\Query\TreeWalker
* 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
@@ -119,15 +110,15 @@ final class Query extends AbstractQuery
private $_dql = null;
/**
* @var \Doctrine\ORM\Query\ParserResult The parser result that holds DQL => SQL information.
* @var Doctrine\ORM\Query\ParserResult The parser result that holds DQL => SQL information.
*/
private $_parserResult;
/**
* @var integer The first result to return (the "offset").
*/
private $_firstResult = null;
/**
* @var integer The maximum number of results to return (the "limit").
*/
@@ -147,7 +138,7 @@ final class Query extends AbstractQuery
* @var int Query Cache lifetime.
*/
private $_queryCacheTTL;
/**
* @var boolean Whether to use a query cache, if available. Defaults to TRUE.
*/
@@ -158,7 +149,7 @@ final class Query extends AbstractQuery
/**
* Initializes a new Query instance.
*
* @param \Doctrine\ORM\EntityManager $entityManager
* @param Doctrine\ORM\EntityManager $entityManager
*/
/*public function __construct(EntityManager $entityManager)
{
@@ -179,9 +170,9 @@ final class Query extends AbstractQuery
/**
* Returns the corresponding AST for this DQL query.
*
* @return \Doctrine\ORM\Query\AST\SelectStatement |
* \Doctrine\ORM\Query\AST\UpdateStatement |
* \Doctrine\ORM\Query\AST\DeleteStatement
* @return Doctrine\ORM\Query\AST\SelectStatement |
* Doctrine\ORM\Query\AST\UpdateStatement |
* Doctrine\ORM\Query\AST\DeleteStatement
*/
public function getAST()
{
@@ -191,22 +182,21 @@ final class Query extends AbstractQuery
/**
* Parses the DQL query, if necessary, and stores the parser result.
*
*
* Note: Populates $this->_parserResult as a side-effect.
*
* @return \Doctrine\ORM\Query\ParserResult
* @return Doctrine\ORM\Query\ParserResult
*/
private function _parse()
{
if ($this->_state === self::STATE_CLEAN) {
return $this->_parserResult;
}
// Check query cache.
if ($this->_useQueryCache && ($queryCache = $this->getQueryCacheDriver())) {
$hash = $this->_getQueryCacheId();
$cached = $this->_expireQueryCache ? false : $queryCache->fetch($hash);
if ($cached === false) {
// Cache miss.
$parser = new Parser($this);
@@ -220,9 +210,8 @@ final class Query extends AbstractQuery
$parser = new Parser($this);
$this->_parserResult = $parser->parse();
}
$this->_state = self::STATE_CLEAN;
return $this->_parserResult;
}
@@ -240,90 +229,49 @@ final class Query extends AbstractQuery
throw QueryException::invalidParameterNumber();
}
list($sqlParams, $types) = $this->processParameterMappings($paramMappings);
if ($this->_resultSetMapping === null) {
$this->_resultSetMapping = $this->_parserResult->getResultSetMapping();
}
return $executor->execute($this->_em->getConnection(), $sqlParams, $types);
}
/**
* Processes query parameter mappings
*
* @param array $paramMappings
* @return array
*/
private function processParameterMappings($paramMappings)
{
$sqlParams = $types = array();
foreach ($this->_params as $key => $value) {
if ( ! isset($paramMappings[$key])) {
throw QueryException::unknownParameter($key);
}
if (isset($this->_paramTypes[$key])) {
foreach ($paramMappings[$key] as $position) {
$types[$position] = $this->_paramTypes[$key];
}
}
$sqlPositions = $paramMappings[$key];
$value = array_values($this->processParameterValue($value));
$countValue = count($value);
for ($i = 0, $l = count($sqlPositions); $i < $l; $i++) {
$sqlParams[$sqlPositions[$i]] = $value[($i % $countValue)];
if (is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value))) {
if ($this->_em->getUnitOfWork()->getEntityState($value) == UnitOfWork::STATE_MANAGED) {
$idValues = $this->_em->getUnitOfWork()->getEntityIdentifier($value);
} else {
$class = $this->_em->getClassMetadata(get_class($value));
$idValues = $class->getIdentifierValues($value);
}
$sqlPositions = $paramMappings[$key];
$cSqlPos = count($sqlPositions);
$cIdValues = count($idValues);
$idValues = array_values($idValues);
for ($i = 0; $i < $cSqlPos; $i++) {
$sqlParams[$sqlPositions[$i]] = $idValues[ ($i % $cIdValues) ];
}
} else {
foreach ($paramMappings[$key] as $position) {
$sqlParams[$position] = $value;
}
}
}
if (count($sqlParams) != count($types)) {
throw QueryException::parameterTypeMissmatch();
}
if ($sqlParams) {
ksort($sqlParams);
$sqlParams = array_values($sqlParams);
ksort($types);
$types = array_values($types);
}
return array($sqlParams, $types);
}
if ($this->_resultSetMapping === null) {
$this->_resultSetMapping = $this->_parserResult->getResultSetMapping();
}
/**
* Process an individual parameter value
*
* @param mixed $value
* @return array
*/
private function processParameterValue($value)
{
if (is_array($value)) {
for ($i = 0, $l = count($value); $i < $l; $i++) {
$paramValue = $this->processParameterValue($value[$i]);
// TODO: What about Entities that have composite primary key?
$value[$i] = is_array($paramValue) ? $paramValue[key($paramValue)] : $paramValue;
}
return array($value);
}
if ( ! (is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(get_class($value)))) {
return array($value);
}
if ($this->_em->getUnitOfWork()->getEntityState($value) === UnitOfWork::STATE_MANAGED) {
return array_values($this->_em->getUnitOfWork()->getEntityIdentifier($value));
}
$class = $this->_em->getClassMetadata(get_class($value));
return array_values($class->getIdentifierValues($value));
return $executor->execute($this->_em->getConnection(), $sqlParams, $types);
}
/**
@@ -337,10 +285,10 @@ final class Query extends AbstractQuery
$this->_queryCache = $queryCache;
return $this;
}
/**
* Defines whether the query should make use of a query cache, if available.
*
*
* @param boolean $bool
* @return @return Query This query instance.
*/
@@ -428,7 +376,7 @@ final class Query extends AbstractQuery
* Sets a DQL query string.
*
* @param string $dqlQuery DQL Query
* @return \Doctrine\ORM\AbstractQuery
* @return Doctrine\ORM\AbstractQuery
*/
public function setDQL($dqlQuery)
{
@@ -474,7 +422,7 @@ final class Query extends AbstractQuery
{
return stripos($this->getDQL(), $dql) === false ? false : true;
}
/**
* Sets the position of the first result to retrieve (the "offset").
*
@@ -487,21 +435,21 @@ final class Query extends AbstractQuery
$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 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 $maxResults
* @return Query This query object.
*/
@@ -511,11 +459,11 @@ final class Query extends AbstractQuery
$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 Maximum number of results.
*/
public function getMaxResults()
@@ -536,7 +484,7 @@ final class Query extends AbstractQuery
$this->setHint(self::HINT_INTERNAL_ITERATION, true);
return parent::iterate($params, $hydrationMode);
}
/**
* {@inheritdoc}
*/
@@ -545,7 +493,7 @@ final class Query extends AbstractQuery
$this->_state = self::STATE_DIRTY;
return parent::setHint($name, $value);
}
/**
* {@inheritdoc}
*/
@@ -558,7 +506,7 @@ final class Query extends AbstractQuery
/**
* Set the lock mode for this Query.
*
* @see \Doctrine\DBAL\LockMode
* @see Doctrine\DBAL\LockMode
* @param int $lockMode
* @return Query
*/
@@ -600,7 +548,7 @@ final class Query extends AbstractQuery
ksort($this->_hints);
return md5(
$this->getDql() . var_export($this->_hints, true) .
$this->getDql() . var_export($this->_hints, true) .
'&firstResult=' . $this->_firstResult . '&maxResult=' . $this->_maxResults .
'&hydrationMode='.$this->_hydrationMode.'DOCTRINE_QUERY_CACHE_SALT'
);
@@ -616,4 +564,4 @@ final class Query extends AbstractQuery
parent::__clone();
$this->_state = self::STATE_DIRTY;
}
}
}
@@ -1,47 +0,0 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Query\AST;
/**
* CoalesceExpression ::= "COALESCE" "(" ScalarExpression {"," ScalarExpression}* ")"
*
* @since 2.1
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class CoalesceExpression extends Node
{
public $scalarExpressions = array();
public function __construct(array $scalarExpressions)
{
$this->scalarExpressions = $scalarExpressions;
}
public function dispatch($sqlWalker)
{
return $sqlWalker->walkCoalesceExpression($this);
}
}
@@ -1,5 +1,7 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -25,6 +27,7 @@ namespace Doctrine\ORM\Query\AST;
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision: 3938 $
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
@@ -1,71 +0,0 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\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(date1, interval, unit)"
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class DateAddFunction extends FunctionNode
{
public $firstDateExpression = null;
public $intervalExpression = null;
public $unit = null;
public function getSql(SqlWalker $sqlWalker)
{
$unit = strtolower($this->unit);
if ($unit == "day") {
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddDaysExpression(
$this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker)
);
} else if ($unit == "month") {
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateAddMonthExpression(
$this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker)
);
} else {
throw QueryException::semanticalError('DATE_ADD() only supports units of type day and month.');
}
}
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);
}
}
@@ -1,58 +0,0 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Query\AST\Functions;
use Doctrine\ORM\Query\Lexer;
use Doctrine\ORM\Query\SqlWalker;
use Doctrine\ORM\Query\Parser;
/**
* "DATE_DIFF(date1, date2)"
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class DateDiffFunction extends FunctionNode
{
public $date1;
public $date2;
public function getSql(SqlWalker $sqlWalker)
{
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateDiffExpression(
$this->date1->dispatch($sqlWalker),
$this->date2->dispatch($sqlWalker)
);
}
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);
}
}
@@ -1,58 +0,0 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\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(date1, interval, unit)"
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class DateSubFunction extends DateAddFunction
{
public $firstDateExpression = null;
public $intervalExpression = null;
public $unit = null;
public function getSql(SqlWalker $sqlWalker)
{
$unit = strtolower($this->unit);
if ($unit == "day") {
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubDaysExpression(
$this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker)
);
} else if ($unit == "month") {
return $sqlWalker->getConnection()->getDatabasePlatform()->getDateSubMonthExpression(
$this->firstDateExpression->dispatch($sqlWalker),
$this->intervalExpression->dispatch($sqlWalker)
);
} else {
throw QueryException::semanticalError('DATE_SUB() only supports units of type day and month.');
}
}
}
@@ -53,8 +53,8 @@ class SizeFunction extends FunctionNode
if ($assoc['type'] == \Doctrine\ORM\Mapping\ClassMetadata::ONE_TO_MANY) {
$targetClass = $sqlWalker->getEntityManager()->getClassMetadata($assoc['targetEntity']);
$targetTableAlias = $sqlWalker->getSQLTableAlias($targetClass->table['name']);
$sourceTableAlias = $sqlWalker->getSQLTableAlias($class->table['name'], $dqlAlias);
$targetTableAlias = $sqlWalker->getSqlTableAlias($targetClass->table['name']);
$sourceTableAlias = $sqlWalker->getSqlTableAlias($class->table['name'], $dqlAlias);
$sql .= $targetClass->getQuotedTableName($platform) . ' ' . $targetTableAlias . ' WHERE ';
@@ -76,8 +76,8 @@ class SizeFunction extends FunctionNode
$joinTable = $owningAssoc['joinTable'];
// SQL table aliases
$joinTableAlias = $sqlWalker->getSQLTableAlias($joinTable['name']);
$sourceTableAlias = $sqlWalker->getSQLTableAlias($class->table['name'], $dqlAlias);
$joinTableAlias = $sqlWalker->getSqlTableAlias($joinTable['name']);
$sourceTableAlias = $sqlWalker->getSqlTableAlias($class->table['name'], $dqlAlias);
// join to target table
$sql .= $targetClass->getQuotedJoinTableName($owningAssoc, $platform) . ' ' . $joinTableAlias . ' WHERE ';
@@ -1,49 +0,0 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Query\AST;
/**
* NullIfExpression ::= "NULLIF" "(" ScalarExpression "," ScalarExpression ")"
*
* @since 2.1
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class NullIfExpression extends Node
{
public $firstExpression;
public $secondExpression;
public function __construct($firstExpression, $secondExpression)
{
$this->firstExpression = $firstExpression;
$this->secondExpression = $secondExpression;
}
public function dispatch($sqlWalker)
{
return $sqlWalker->walkNullIfExpression($this);
}
}
@@ -49,9 +49,9 @@ abstract class AbstractSqlExecutor
/**
* Executes all sql statements.
*
* @param \Doctrine\DBAL\Connection $conn The database connection that is used to execute the queries.
* @param Doctrine\DBAL\Connection $conn The database connection that is used to execute the queries.
* @param array $params The parameters.
* @return \Doctrine\DBAL\Driver\Statement
* @return Doctrine\DBAL\Driver\Statement
*/
abstract public function execute(Connection $conn, array $params, array $types);
}
@@ -63,11 +63,9 @@ class MultiTableDeleteExecutor extends AbstractSqlExecutor
$idColumnList = implode(', ', $idColumnNames);
// 1. Create an INSERT INTO temptable ... SELECT identifiers WHERE $AST->getWhereClause()
$sqlWalker->setSQLTableAlias($primaryClass->table['name'], 't0', $primaryDqlAlias);
$this->_insertSql = 'INSERT INTO ' . $tempTable . ' (' . $idColumnList . ')'
. ' SELECT t0.' . implode(', t0.', $idColumnNames);
$sqlWalker->setSqlTableAlias($primaryClass->table['name'] . $primaryDqlAlias, 't0');
$rangeDecl = new AST\RangeVariableDeclaration($primaryClass->name, $primaryDqlAlias);
$fromClause = new AST\FromClause(array(new AST\IdentificationVariableDeclaration($rangeDecl, null, array())));
$this->_insertSql .= $sqlWalker->walkFromClause($fromClause);
@@ -98,13 +96,13 @@ class MultiTableDeleteExecutor extends AbstractSqlExecutor
}
$this->_createTempTableSql = $platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable . ' ('
. $platform->getColumnDeclarationListSQL($columnDefinitions) . ')';
$this->_dropTempTableSql = $platform->getDropTemporaryTableSQL($tempTable);
$this->_dropTempTableSql = 'DROP TABLE ' . $tempTable;
}
/**
* Executes all SQL statements.
*
* @param \Doctrine\DBAL\Connection $conn The database connection that is used to execute the queries.
* @param Doctrine\DBAL\Connection $conn The database connection that is used to execute the queries.
* @param array $params The parameters.
* @override
*/
@@ -51,7 +51,7 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
$em = $sqlWalker->getEntityManager();
$conn = $em->getConnection();
$platform = $conn->getDatabasePlatform();
$updateClause = $AST->updateClause;
$primaryClass = $sqlWalker->getEntityManager()->getClassMetadata($updateClause->abstractSchemaName);
@@ -64,14 +64,11 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
$idColumnList = implode(', ', $idColumnNames);
// 1. Create an INSERT INTO temptable ... SELECT identifiers WHERE $AST->getWhereClause()
$sqlWalker->setSQLTableAlias($primaryClass->table['name'], 't0', $updateClause->aliasIdentificationVariable);
$this->_insertSql = 'INSERT INTO ' . $tempTable . ' (' . $idColumnList . ')'
. ' SELECT t0.' . implode(', t0.', $idColumnNames);
$sqlWalker->setSqlTableAlias($primaryClass->table['name'] . $updateClause->aliasIdentificationVariable, 't0');
$rangeDecl = new AST\RangeVariableDeclaration($primaryClass->name, $updateClause->aliasIdentificationVariable);
$fromClause = new AST\FromClause(array(new AST\IdentificationVariableDeclaration($rangeDecl, null, array())));
$this->_insertSql .= $sqlWalker->walkFromClause($fromClause);
// 2. Create ID subselect statement used in UPDATE ... WHERE ... IN (subselect)
@@ -88,9 +85,8 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
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'])) {
isset($class->associationMappings[$field]) && ! isset($class->associationMappings[$field]['inherited'])) {
$newValue = $updateItem->newValue;
if ( ! $affected) {
@@ -106,9 +102,7 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
//FIXME (URGENT): With query cache the parameter is out of date. Move to execute() stage.
if ($newValue instanceof AST\InputParameter) {
$paramKey = $newValue->name;
$this->_sqlParameters[$i]['parameters'][] = $sqlWalker->getQuery()->getParameter($paramKey);
$this->_sqlParameters[$i]['types'][] = $sqlWalker->getQuery()->getParameterType($paramKey);
$this->_sqlParameters[$i][] = $sqlWalker->getQuery()->getParameter($paramKey);
++$this->_numParametersInUpdateClause;
}
}
@@ -126,18 +120,15 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
// 4. Store DDL for temporary identifier table.
$columnDefinitions = array();
foreach ($idColumnNames as $idColumnName) {
$columnDefinitions[$idColumnName] = array(
'notnull' => true,
'type' => Type::getType($rootClass->getTypeOfColumn($idColumnName))
);
}
$this->_createTempTableSql = $platform->getCreateTemporaryTableSnippetSQL() . ' ' . $tempTable . ' ('
. $platform->getColumnDeclarationListSQL($columnDefinitions) . ')';
$this->_dropTempTableSql = $platform->getDropTemporaryTableSQL($tempTable);
$this->_dropTempTableSql = 'DROP TABLE ' . $tempTable;
}
/**
@@ -155,23 +146,11 @@ class MultiTableUpdateExecutor extends AbstractSqlExecutor
$conn->executeUpdate($this->_createTempTableSql);
// 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)
);
$numUpdated = $conn->executeUpdate($this->_insertSql, array_slice($params, $this->_numParametersInUpdateClause), $types);
// Execute UPDATE statements
for ($i=0, $count=count($this->_sqlStatements); $i<$count; ++$i) {
$parameters = array();
$types = array();
if (isset($this->_sqlParameters[$i])) {
$parameters = isset($this->_sqlParameters[$i]['parameters']) ? $this->_sqlParameters[$i]['parameters'] : array();
$types = isset($this->_sqlParameters[$i]['types']) ? $this->_sqlParameters[$i]['types'] : array();
}
$conn->executeUpdate($this->_sqlStatements[$i], $parameters, $types);
$conn->executeUpdate($this->_sqlStatements[$i], isset($this->_sqlParameters[$i]) ? $this->_sqlParameters[$i] : array());
}
// Drop temporary table
-22
View File
@@ -443,28 +443,6 @@ class Expr
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.
*
+2 -2
View File
@@ -32,9 +32,9 @@ namespace Doctrine\ORM\Query\Expr;
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class Andx extends Composite
class Andx extends Base
{
protected $_separator = ' AND ';
protected $_separator = ') AND (';
protected $_allowedClasses = array(
'Doctrine\ORM\Query\Expr\Comparison',
'Doctrine\ORM\Query\Expr\Func',
+1 -1
View File
@@ -39,7 +39,7 @@ abstract class Base
protected $_postSeparator = ')';
protected $_allowedClasses = array();
protected $_parts = array();
private $_parts = array();
public function __construct($args = array())
{
-68
View File
@@ -1,68 +0,0 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Query\Expr;
/**
* Expression class for building DQL and parts
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @version $Revision$
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class Composite extends Base
{
public function __toString()
{
if ($this->count() === 1) {
return (string) $this->_parts[0];
}
$components = array();
foreach ($this->_parts as $part) {
$components[] = $this->processQueryPart($part);
}
return implode($this->_separator, $components);
}
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 (mb_stripos($queryPart, ' OR ') !== false || mb_stripos($queryPart, ' AND ') !== false) {
return $this->_preSeparator . $queryPart . $this->_postSeparator;
}
return $queryPart;
}
}
+6 -9
View File
@@ -45,23 +45,20 @@ class Join
private $_alias;
private $_conditionType;
private $_condition;
private $_indexBy;
public function __construct($joinType, $join, $alias = null, $conditionType = null, $condition = null, $indexBy = null)
public function __construct($joinType, $join, $alias = null, $conditionType = null, $condition = null)
{
$this->_joinType = $joinType;
$this->_join = $join;
$this->_alias = $alias;
$this->_joinType = $joinType;
$this->_join = $join;
$this->_alias = $alias;
$this->_conditionType = $conditionType;
$this->_condition = $condition;
$this->_indexBy = $indexBy;
$this->_condition = $condition;
}
public function __toString()
{
return strtoupper($this->_joinType) . ' JOIN ' . $this->_join
. ($this->_alias ? ' ' . $this->_alias : '')
. ($this->_condition ? ' ' . strtoupper($this->_conditionType) . ' ' . $this->_condition : '')
. ($this->_indexBy ? ' INDEX BY ' . $this->_indexBy : '');
. ($this->_condition ? ' ' . strtoupper($this->_conditionType) . ' ' . $this->_condition : '');
}
}
+2 -2
View File
@@ -32,9 +32,9 @@ namespace Doctrine\ORM\Query\Expr;
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class Orx extends Composite
class Orx extends Base
{
protected $_separator = ' OR ';
protected $_separator = ') OR (';
protected $_allowedClasses = array(
'Doctrine\ORM\Query\Expr\Andx',
'Doctrine\ORM\Query\Expr\Comparison',
+1 -1
View File
@@ -126,7 +126,7 @@ class Lexer extends \Doctrine\Common\Lexer
'[a-z_\\\][a-z0-9_\:\\\]*[a-z0-9_]{1}',
'(?:[0-9]+(?:[\.][0-9]+)*)(?:e[+-]?[0-9]+)?',
"'(?:[^']|'')*'",
'\?[0-9]*|:[a-z]{1}[a-z0-9_]{0,}'
'\?[1-9][0-9]*|:[a-z]{1}[a-z0-9_]{0,}'
);
}
@@ -1,72 +0,0 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Query;
use Doctrine\DBAL\Connection,
Doctrine\DBAL\Types\Type;
/**
* Provides an enclosed support for parameter infering.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.0
* @author Benjamin Eberlei <kontakt@beberlei.de>
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
*/
class ParameterTypeInferer
{
/**
* Infer 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)
{
switch (true) {
case is_integer($value):
return Type::INTEGER;
case ($value instanceof \DateTime):
return Type::DATETIME;
case is_array($value):
$key = key($value);
if (is_integer($value[$key])) {
return Connection::PARAM_INT_ARRAY;
}
return Connection::PARAM_STR_ARRAY;
default:
// Do nothing
break;
}
return \PDO::PARAM_STR;
}
}
+26 -98
View File
@@ -45,22 +45,19 @@ class Parser
/** READ-ONLY: Maps BUILT-IN numeric function names to AST class names. */
private static $_NUMERIC_FUNCTIONS = array(
'length' => 'Doctrine\ORM\Query\AST\Functions\LengthFunction',
'locate' => 'Doctrine\ORM\Query\AST\Functions\LocateFunction',
'abs' => 'Doctrine\ORM\Query\AST\Functions\AbsFunction',
'sqrt' => 'Doctrine\ORM\Query\AST\Functions\SqrtFunction',
'mod' => 'Doctrine\ORM\Query\AST\Functions\ModFunction',
'size' => 'Doctrine\ORM\Query\AST\Functions\SizeFunction',
'date_diff' => 'Doctrine\ORM\Query\AST\Functions\DateDiffFunction',
'length' => 'Doctrine\ORM\Query\AST\Functions\LengthFunction',
'locate' => 'Doctrine\ORM\Query\AST\Functions\LocateFunction',
'abs' => 'Doctrine\ORM\Query\AST\Functions\AbsFunction',
'sqrt' => 'Doctrine\ORM\Query\AST\Functions\SqrtFunction',
'mod' => 'Doctrine\ORM\Query\AST\Functions\ModFunction',
'size' => 'Doctrine\ORM\Query\AST\Functions\SizeFunction'
);
/** READ-ONLY: Maps BUILT-IN datetime function names to AST class names. */
private static $_DATETIME_FUNCTIONS = array(
'current_date' => 'Doctrine\ORM\Query\AST\Functions\CurrentDateFunction',
'current_time' => 'Doctrine\ORM\Query\AST\Functions\CurrentTimeFunction',
'current_timestamp' => 'Doctrine\ORM\Query\AST\Functions\CurrentTimestampFunction',
'date_add' => 'Doctrine\ORM\Query\AST\Functions\DateAddFunction',
'date_sub' => 'Doctrine\ORM\Query\AST\Functions\DateSubFunction',
'current_timestamp' => 'Doctrine\ORM\Query\AST\Functions\CurrentTimestampFunction'
);
/**
@@ -75,14 +72,14 @@ class Parser
/**
* The lexer.
*
* @var \Doctrine\ORM\Query\Lexer
* @var Doctrine\ORM\Query\Lexer
*/
private $_lexer;
/**
* The parser result.
*
* @var \Doctrine\ORM\Query\ParserResult
* @var Doctrine\ORM\Query\ParserResult
*/
private $_parserResult;
@@ -170,7 +167,7 @@ class Parser
/**
* Gets the lexer used by the parser.
*
* @return \Doctrine\ORM\Query\Lexer
* @return Doctrine\ORM\Query\Lexer
*/
public function getLexer()
{
@@ -180,7 +177,7 @@ class Parser
/**
* Gets the ParserResult that is being filled with information during parsing.
*
* @return \Doctrine\ORM\Query\ParserResult
* @return Doctrine\ORM\Query\ParserResult
*/
public function getParserResult()
{
@@ -234,7 +231,7 @@ class Parser
* If they match, updates the lookahead token; otherwise raises a syntax
* error.
*
* @param int token type
* @param int|string token type or value
* @return void
* @throws QueryException If the tokens dont match.
*/
@@ -926,10 +923,6 @@ class Parser
$token = $this->_lexer->lookahead;
$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);
@@ -1466,7 +1459,7 @@ class Parser
/**
* RangeVariableDeclaration ::= AbstractSchemaName ["AS"] AliasIdentificationVariable
*
* @return \Doctrine\ORM\Query\AST\RangeVariableDeclaration
* @return Doctrine\ORM\Query\AST\RangeVariableDeclaration
*/
public function RangeVariableDeclaration()
{
@@ -1537,7 +1530,7 @@ class Parser
* Join ::= ["LEFT" ["OUTER"] | "INNER"] "JOIN" JoinAssociationPathExpression
* ["AS"] AliasIdentificationVariable ["WITH" ConditionalExpression]
*
* @return \Doctrine\ORM\Query\AST\Join
* @return Doctrine\ORM\Query\AST\Join
*/
public function Join()
{
@@ -1607,7 +1600,7 @@ class Parser
/**
* IndexBy ::= "INDEX" "BY" StateFieldPathExpression
*
* @return \Doctrine\ORM\Query\AST\IndexBy
* @return Doctrine\ORM\Query\AST\IndexBy
*/
public function IndexBy()
{
@@ -1644,10 +1637,6 @@ class Parser
return $this->StateFieldPathExpression();
} else if ($lookahead == Lexer::T_INTEGER || $lookahead == Lexer::T_FLOAT) {
return $this->SimpleArithmeticExpression();
} else if ($lookahead == Lexer::T_CASE || $lookahead == Lexer::T_COALESCE || $lookahead == Lexer::T_NULLIF) {
// Since NULLIF and COALESCE can be identified as a function,
// we need to check if before check for FunctionDeclaration
return $this->CaseExpression();
} else if ($this->_isFunction() || $this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
// We may be in an ArithmeticExpression (find the matching ")" and inspect for Math operator)
$this->_lexer->peek(); // "("
@@ -1669,6 +1658,8 @@ class Parser
} else if ($lookahead == Lexer::T_TRUE || $lookahead == Lexer::T_FALSE) {
$this->match($lookahead);
return new AST\Literal(AST\Literal::BOOLEAN, $this->_lexer->token['value']);
} else if ($lookahead == Lexer::T_CASE || $lookahead == Lexer::T_COALESCE || $lookahead == Lexer::T_NULLIF) {
return $this->CaseExpression();
} else {
$this->syntaxError();
}
@@ -1676,66 +1667,11 @@ class Parser
public function CaseExpression()
{
$lookahead = $this->_lexer->lookahead['type'];
// if "CASE" "WHEN" => GeneralCaseExpression
// else if "CASE" => SimpleCaseExpression
// [DONE] else if "COALESCE" => CoalesceExpression
// [DONE] else if "NULLIF" => NullifExpression
switch ($lookahead) {
case Lexer::T_NULLIF:
return $this->NullIfExpression();
case Lexer::T_COALESCE:
return $this->CoalesceExpression();
default:
$this->semanticalError('CaseExpression not yet supported.');
return null;
}
}
/**
* 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 = array();
$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\ExistsExpression
*/
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);
// else if "COALESCE" => CoalesceExpression
// else if "NULLIF" => NullifExpression
$this->semanticalError('CaseExpression not yet supported.');
}
/**
@@ -1743,7 +1679,7 @@ class Parser
* IdentificationVariable | StateFieldPathExpression |
* (AggregateExpression | "(" Subselect ")" | ScalarExpression) [["AS"] AliasResultVariable]
*
* @return \Doctrine\ORM\Query\AST\SelectExpression
* @return Doctrine\ORM\Query\AST\SelectExpression
*/
public function SelectExpression()
{
@@ -1774,16 +1710,12 @@ class Parser
}
} else if ($this->_isFunction()) {
$this->_lexer->peek(); // "("
$lookaheadType = $this->_lexer->lookahead['type'];
$beyond = $this->_peekBeyondClosingParenthesis();
$beyond = $this->_peekBeyondClosingParenthesis();
if ($this->_isMathOperator($beyond)) {
$expression = $this->ScalarExpression();
} else if ($this->_isAggregateFunction($this->_lexer->lookahead['type'])) {
$expression = $this->AggregateExpression();
} else if (in_array ($lookaheadType, array(Lexer::T_CASE, Lexer::T_COALESCE, Lexer::T_NULLIF))) {
$expression = $this->CaseExpression();
} else {
// Shortcut: ScalarExpression => Function
$expression = $this->FunctionDeclaration();
@@ -1967,7 +1899,7 @@ class Parser
/**
* ConditionalPrimary ::= SimpleConditionalExpression | "(" ConditionalExpression ")"
*
* @return \Doctrine\ORM\Query\AST\ConditionalPrimary
* @return Doctrine\ORM\Query\AST\ConditionalPrimary
*/
public function ConditionalPrimary()
{
@@ -2290,7 +2222,7 @@ class Parser
/**
* ArithmeticPrimary ::= SingleValuedPathExpression | Literal | "(" SimpleArithmeticExpression ")"
* | FunctionsReturningNumerics | AggregateExpression | FunctionsReturningStrings
* | FunctionsReturningDatetime | IdentificationVariable | ResultVariable
* | FunctionsReturningDatetime | IdentificationVariable
*/
public function ArithmeticPrimary()
{
@@ -2314,11 +2246,7 @@ class Parser
if ($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:
+1 -12
View File
@@ -72,11 +72,6 @@ class QueryException extends \Doctrine\ORM\ORMException
return new self("Invalid parameter: token ".$key." is not defined in the query.");
}
public static function parameterTypeMissmatch()
{
return new self("DQL Query parameter and type numbers missmatch, but have to be exactly equal.");
}
public static function invalidPathExpression($pathExpr)
{
return new self(
@@ -89,7 +84,7 @@ class QueryException extends \Doctrine\ORM\ORMException
}
/**
* @param \Doctrine\ORM\Mapping\AssociationMapping $assoc
* @param Doctrine\ORM\Mapping\AssociationMapping $assoc
*/
public static function iterateWithFetchJoinCollectionNotAllowed($assoc)
{
@@ -140,10 +135,4 @@ class QueryException extends \Doctrine\ORM\ORMException
"in the query."
);
}
public static function instanceOfUnrelatedClass($className, $rootClass)
{
return new self("Cannot check if a child of '" . $rootClass . "' is instanceof '" . $className . "', " .
"inheritance hierachy exists between these two classes.");
}
}
+8 -16
View File
@@ -1,5 +1,7 @@
<?php
/*
* $Id$
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
@@ -112,13 +114,6 @@ class ResultSetMapping
* @var array
*/
public $declaringClasses = array();
/**
* This is necessary to hydrate derivate foreign keys correctly.
*
* @var array
*/
public $isIdentifierColumn = array();
/**
* Adds an entity result to this ResultSetMapping.
@@ -388,17 +383,14 @@ class ResultSetMapping
/**
* Adds a meta column (foreign key or discriminator column) to the result set.
*
* @param string $alias
* @param string $columnName
* @param string $fieldName
* @param bool
* @param $alias
* @param $columnName
* @param $fieldName
*/
public function addMetaResult($alias, $columnName, $fieldName, $isIdentifierColumn = false)
public function addMetaResult($alias, $columnName, $fieldName)
{
$this->metaMappings[$columnName] = $fieldName;
$this->columnOwnerMap[$columnName] = $alias;
if ($isIdentifierColumn) {
$this->isIdentifierColumn[$alias][$columnName] = true;
}
}
}
}
@@ -1,107 +0,0 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Query;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
/**
* A ResultSetMappingBuilder uses the EntityManager to automatically populate entity fields
*
* @author Michael Ridgway <mcridgway@gmail.com>
* @since 2.1
*/
class ResultSetMappingBuilder extends ResultSetMapping
{
/**
* @var EntityManager
*/
private $em;
/**
* @param EntityManager
*/
public function __construct(EntityManager $em)
{
$this->em = $em;
}
/**
* 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)
*/
public function addRootEntityFromClassMetadata($class, $alias, $renamedColumns = array())
{
$this->addEntityResult($class, $alias);
$this->addAllClassFields($class, $alias, $renamedColumns);
}
/**
* 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 object $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)
*/
public function addJoinedEntityFromClassMetadata($class, $alias, $parentAlias, $relation, $renamedColumns = array())
{
$this->addJoinedEntityResult($class, $alias, $parentAlias, $relation);
$this->addAllClassFields($class, $alias, $renamedColumns);
}
/**
* Adds all fields of the given class to the result set mapping (columns and meta fields)
*/
protected function addAllClassFields($class, $alias, $renamedColumns = array())
{
$classMetadata = $this->em->getClassMetadata($class);
if ($classMetadata->isInheritanceTypeSingleTable() || $classMetadata->isInheritanceTypeJoined()) {
throw new \InvalidArgumentException('ResultSetMapping builder does not currently support inheritance.');
}
$platform = $this->em->getConnection()->getDatabasePlatform();
foreach ($classMetadata->getColumnNames() AS $columnName) {
$propertyName = $classMetadata->getFieldName($columnName);
if (isset($renamedColumns[$columnName])) {
$columnName = $renamedColumns[$columnName];
}
if (isset($this->fieldMappings[$columnName])) {
throw new \InvalidArgumentException("The column '$columnName' conflicts with another column in the mapper.");
}
$this->addFieldResult($alias, $platform->getSQLResultCasing($columnName), $propertyName);
}
foreach ($classMetadata->associationMappings AS $associationMapping) {
if ($associationMapping['isOwningSide'] && $associationMapping['type'] & ClassMetadataInfo::TO_ONE) {
foreach ($associationMapping['joinColumns'] AS $joinColumn) {
$columnName = $joinColumn['name'];
$renamedColumnName = isset($renamedColumns[$columnName]) ? $renamedColumns[$columnName] : $columnName;
if (isset($this->metaMappings[$renamedColumnName])) {
throw new \InvalidArgumentException("The column '$renamedColumnName' conflicts with another column in the mapper.");
}
$this->addMetaResult($alias, $platform->getSQLResultCasing($renamedColumnName), $platform->getSQLResultCasing($columnName));
}
}
}
}
}
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -55,7 +55,7 @@ abstract class TreeWalkerAdapter implements TreeWalker
/**
* Retrieve Query Instance reponsible for the current walkers execution.
*
* @return \Doctrine\ORM\Query
* @return Doctrine\ORM\Query
*/
protected function _getQuery()
{
@@ -65,7 +65,7 @@ abstract class TreeWalkerAdapter implements TreeWalker
/**
* Retrieve ParserResult
*
* @return \Doctrine\ORM\Query\ParserResult
* @return Doctrine\ORM\Query\ParserResult
*/
protected function _getParserResult()
{
+26 -156
View File
@@ -217,92 +217,25 @@ class QueryBuilder
->setFirstResult($this->_firstResult)
->setMaxResults($this->_maxResults);
}
/**
* Gets the FIRST root alias of the query. This is the first entity alias involved
* Gets the root alias of the query. This is the first entity alias involved
* in the construction of the query.
*
* <code>
* $qb = $em->createQueryBuilder()
* ->select('u')
* ->from('User', 'u');
* $qb = $em->createQueryBuilder()
* ->select('u')
* ->from('User', 'u');
*
* echo $qb->getRootAlias(); // u
* echo $qb->getRootAlias(); // u
* </code>
*
* @deprecated Please use $qb->getRootAliases() instead.
* @return string $rootAlias
* @todo Rename/Refactor: getRootAliases(), there can be multiple roots!
*/
public function getRootAlias()
{
$aliases = $this->getRootAliases();
return $aliases[0];
}
/**
* Gets the root aliases of the query. This is the entity aliases involved
* in the construction of the query.
*
* <code>
* $qb = $em->createQueryBuilder()
* ->select('u')
* ->from('User', 'u');
*
* $qb->getRootAliases(); // array('u')
* </code>
*
* @return array $rootAliases
*/
public function getRootAliases()
{
$aliases = array();
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 the root entities of the query. This is the entity aliases involved
* in the construction of the query.
*
* <code>
* $qb = $em->createQueryBuilder()
* ->select('u')
* ->from('User', 'u');
*
* $qb->getRootEntities(); // array('User')
* </code>
*
* @return array $rootEntities
*/
public function getRootEntities()
{
$entities = array();
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;
return $this->_dqlParts['from'][0]->getAlias();
}
/**
@@ -323,13 +256,10 @@ class QueryBuilder
*/
public function setParameter($key, $value, $type = null)
{
if ($type === null) {
$type = Query\ParameterTypeInferer::inferType($value);
if ($type !== null) {
$this->_paramTypes[$key] = $type;
}
$this->_paramTypes[$key] = $type;
$this->_params[$key] = $value;
return $this;
}
@@ -352,13 +282,8 @@ class QueryBuilder
*/
public function setParameters(array $params, array $types = array())
{
foreach ($params as $key => $value) {
if (isset($types[$key])) {
$this->setParameter($key, $value, $types[$key]);
} else {
$this->setParameter($key, $value);
}
}
$this->_paramTypes = $types;
$this->_params = $params;
return $this;
}
@@ -443,29 +368,9 @@ class QueryBuilder
public function add($dqlPartName, $dqlPart, $append = false)
{
$isMultiple = is_array($this->_dqlParts[$dqlPartName]);
// This is introduced for backwards compatibility reasons.
// TODO: Remove for 3.0
if ($dqlPartName == 'join') {
$newDqlPart = array();
foreach ($dqlPart AS $k => $v) {
if (is_numeric($k)) {
$newDqlPart[$this->getRootAlias()] = $v;
} else {
$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;
}
$this->_dqlParts[$dqlPartName][] = $dqlPart;
} else {
$this->_dqlParts[$dqlPartName] = ($isMultiple) ? array($dqlPart) : $dqlPart;
}
@@ -618,12 +523,11 @@ class QueryBuilder
* @param string $alias The alias of the join
* @param string $conditionType The condition type constant. Either ON or WITH.
* @param string $condition The condition for the join
* @param string $indexBy The index for the join
* @return QueryBuilder This QueryBuilder instance.
*/
public function join($join, $alias, $conditionType = null, $condition = null, $indexBy = null)
public function join($join, $alias, $conditionType = null, $condition = null)
{
return $this->innerJoin($join, $alias, $conditionType, $condition, $indexBy);
return $this->innerJoin($join, $alias, $conditionType, $condition);
}
/**
@@ -643,18 +547,12 @@ class QueryBuilder
* @param string $alias The alias of the join
* @param string $conditionType The condition type constant. Either ON or WITH.
* @param string $condition The condition for the join
* @param string $indexBy The index for the join
* @return QueryBuilder This QueryBuilder instance.
*/
public function innerJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null)
public function innerJoin($join, $alias, $conditionType = null, $condition = null)
{
$rootAlias = substr($join, 0, strpos($join, '.'));
if (!in_array($rootAlias, $this->getRootAliases())) {
$rootAlias = $this->getRootAlias();
}
return $this->add('join', array(
$rootAlias => new Expr\Join(Expr\Join::INNER_JOIN, $join, $alias, $conditionType, $condition, $indexBy)
return $this->add('join', new Expr\Join(
Expr\Join::INNER_JOIN, $join, $alias, $conditionType, $condition
), true);
}
@@ -676,18 +574,12 @@ class QueryBuilder
* @param string $alias The alias of the join
* @param string $conditionType The condition type constant. Either ON or WITH.
* @param string $condition The condition for the join
* @param string $indexBy The index for the join
* @return QueryBuilder This QueryBuilder instance.
*/
public function leftJoin($join, $alias, $conditionType = null, $condition = null, $indexBy = null)
public function leftJoin($join, $alias, $conditionType = null, $condition = null)
{
$rootAlias = substr($join, 0, strpos($join, '.'));
if (!in_array($rootAlias, $this->getRootAliases())) {
$rootAlias = $this->getRootAlias();
}
return $this->add('join', array(
$rootAlias => new Expr\Join(Expr\Join::LEFT_JOIN, $join, $alias, $conditionType, $condition, $indexBy)
return $this->add('join', new Expr\Join(
Expr\Join::LEFT_JOIN, $join, $alias, $conditionType, $condition
), true);
}
@@ -737,7 +629,7 @@ class QueryBuilder
*/
public function where($predicates)
{
if ( ! (func_num_args() == 1 && $predicates instanceof Expr\Composite)) {
if ( ! (func_num_args() == 1 && ($predicates instanceof Expr\Andx || $predicates instanceof Expr\Orx))) {
$predicates = new Expr\Andx(func_get_args());
}
@@ -973,36 +865,14 @@ class QueryBuilder
private function _getDQLForSelect()
{
$dql = 'SELECT' . $this->_getReducedDQLQueryPart('select', array('pre' => ' ', 'separator' => ', '));
$fromParts = $this->getDQLPart('from');
$joinParts = $this->getDQLPart('join');
$fromClauses = array();
// 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)
return 'SELECT'
. $this->_getReducedDQLQueryPart('select', array('pre' => ' ', 'separator' => ', '))
. $this->_getReducedDQLQueryPart('from', array('pre' => ' FROM ', 'separator' => ', '))
. $this->_getReducedDQLQueryPart('join', array('pre' => ' ', 'separator' => ' '))
. $this->_getReducedDQLQueryPart('where', array('pre' => ' WHERE '))
. $this->_getReducedDQLQueryPart('groupBy', array('pre' => ' GROUP BY ', 'separator' => ', '))
. $this->_getReducedDQLQueryPart('having', array('pre' => ' HAVING '))
. $this->_getReducedDQLQueryPart('orderBy', array('pre' => ' ORDER BY ', 'separator' => ', '));
return $dql;
}
private function _getReducedDQLQueryPart($queryPartName, $options = array())
@@ -78,10 +78,6 @@ class ConvertMappingCommand extends Console\Command\Command
'num-spaces', null, InputOption::VALUE_OPTIONAL,
'Defines the number of indentation spaces', 4
),
new InputOption(
'namespace', null, InputOption::VALUE_OPTIONAL,
'Defines a namespace for the generated entity classes, if converted from database.'
),
))
->setHelp(<<<EOT
Convert mapping information between supported formats.
@@ -111,17 +107,11 @@ EOT
$em = $this->getHelper('em')->getEntityManager();
if ($input->getOption('from-database') === true) {
$databaseDriver = new \Doctrine\ORM\Mapping\Driver\DatabaseDriver(
$em->getConnection()->getSchemaManager()
);
$em->getConfiguration()->setMetadataDriverImpl(
$databaseDriver
new \Doctrine\ORM\Mapping\Driver\DatabaseDriver(
$em->getConnection()->getSchemaManager()
)
);
if (($namespace = $input->getOption('namespace')) !== null) {
$databaseDriver->setNamespace($namespace);
}
}
$cmf = new DisconnectedClassMetadataFactory();
@@ -1,80 +0,0 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Tools\Console\Command;
use Doctrine\ORM\Mapping\MappingException;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Command\Command;
/**
* Show information about mapped entities
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
* @since 2.1
* @author Benjamin Eberlei <kontakt@beberlei.de>
*/
class InfoCommand extends Command
{
protected function configure()
{
$this
->setName('orm:info')
->setDescription('Show basic information about all mapped entities')
->setHelp(<<<EOT
The <info>doctrine:mapping:info</info> shows basic information about which
entities exist and possibly if their mapping information contains errors or
not.
EOT
);
}
protected function execute(InputInterface $input, OutputInterface $output)
{
/* @var $entityManager \Doctrine\ORM\EntityManager */
$entityManager = $this->getHelper('em')->getEntityManager();
$entityClassNames = $entityManager->getConfiguration()
->getMetadataDriverImpl()
->getAllClassNames();
if (!$entityClassNames) {
throw new \Exception(
'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.'
);
}
$output->writeln(sprintf("Found <info>%d</info> mapped entities:", count($entityClassNames)));
foreach ($entityClassNames as $entityClassName) {
try {
$cm = $entityManager->getClassMetadata($entityClassName);
$output->writeln(sprintf("<info>[OK]</info> %s", $entityClassName));
} catch (MappingException $e) {
$output->writeln("<error>[FAIL]</error> ".$entityClassName);
$output->writeln(sprintf("<comment>%s</comment>", $e->getMessage()));
$output->writeln('');
}
}
}
}
@@ -65,7 +65,7 @@ EOT
protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas)
{
$output->write('ATTENTION: This operation should not be executed in a production environment.' . PHP_EOL . PHP_EOL);
$output->write('ATTENTION: This operation should not be executed in an production enviroment.' . PHP_EOL . PHP_EOL);
if ($input->getOption('dump-sql') === true) {
$sqls = $schemaTool->getCreateSchemaSql($metadatas);
@@ -92,7 +92,7 @@ EOT
}
$output->write('Database schema dropped successfully!' . PHP_EOL);
} else {
$output->write('ATTENTION: This operation should not be executed in a production environment.' . PHP_EOL . PHP_EOL);
$output->write('ATTENTION: This operation should not be executed in an production enviroment.' . PHP_EOL . PHP_EOL);
if ($isFullDatabaseDrop) {
$sqls = $schemaTool->getDropDatabaseSQL();
@@ -28,8 +28,7 @@ use Symfony\Component\Console\Input\InputArgument,
Doctrine\ORM\Tools\SchemaTool;
/**
* Command to generate the SQL needed to update the database schema to match
* the current mapping information.
* Command to update the database schema for a set of classes based on their mappings.
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
@@ -39,58 +38,37 @@ use Symfony\Component\Console\Input\InputArgument,
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
* @author Jonathan Wage <jonwage@gmail.com>
* @author Roman Borschel <roman@code-factory.org>
* @author Ryan Weaver <ryan@thatsquality.com>
*/
class UpdateCommand extends AbstractCommand
{
protected $name = 'orm:schema-tool:update';
/**
* @see Console\Command\Command
*/
protected function configure()
{
$this
->setName($this->name)
->setName('orm:schema-tool:update')
->setDescription(
'Executes (or dumps) the SQL needed to update the database schema to match the current mapping metadata.'
'Processes the schema and either update the database schema of EntityManager Storage Connection or generate the SQL output.'
)
->setDefinition(array(
new InputOption(
'complete', null, InputOption::VALUE_NONE,
'If defined, all assets of the database which are not relevant to the current metadata will be dropped.'
),
new InputOption(
'dump-sql', null, InputOption::VALUE_NONE,
'Dumps the generated SQL statements to the screen (does not execute them).'
'Instead of try to apply generated SQLs into EntityManager Storage Connection, output them.'
),
new InputOption(
'force', null, InputOption::VALUE_NONE,
'Causes the generated SQL statements to be physically executed against your database.'
"Don't ask for the incremental update of the database, but force the operation to run."
),
));
$fullName = $this->getName();
$this->setHelp(<<<EOT
The <info>$fullName</info> 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:
<info>$fullName --dump-sql</info>
Alternatively, you can execute the generated queries:
<info>$fullName --force</info>
Finally, be aware that if the <info>--complete</info> 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.
))
->setHelp(<<<EOT
Processes the schema and either update the database schema of EntityManager Storage Connection or generate the SQL output.
Beware that if --complete is not defined, it will do a save update, which does not delete any tables, sequences or affected foreign keys.
If defined, all assets of the database which are not relevant to the current metadata are dropped by this command.
EOT
);
}
@@ -100,36 +78,26 @@ EOT
// Defining if update is complete or not (--complete not defined means $saveMode = true)
$saveMode = ($input->getOption('complete') !== true);
$sqls = $schemaTool->getUpdateSchemaSql($metadatas, $saveMode);
if (0 == count($sqls)) {
$output->writeln('Nothing to update - your database is already in sync with the current entity metadata.');
return;
}
$dumpSql = (true === $input->getOption('dump-sql'));
$force = (true === $input->getOption('force'));
if ($dumpSql && $force) {
throw new \InvalidArgumentException('You can pass either the --dump-sql or the --force option (but not both simultaneously).');
}
if ($dumpSql) {
$output->writeln(implode(';' . PHP_EOL, $sqls));
} else if ($force) {
$output->writeln('Updating database schema...');
if ($input->getOption('dump-sql') === true) {
$sqls = $schemaTool->getUpdateSchemaSql($metadatas, $saveMode);
$output->write(implode(';' . PHP_EOL, $sqls) . PHP_EOL);
} else if ($input->getOption('force') === true) {
$output->write('Updating database schema...' . PHP_EOL);
$schemaTool->updateSchema($metadatas, $saveMode);
$output->writeln(sprintf('Database schema updated successfully! "<info>%s</info>" queries were executed', count($sqls)));
$output->write('Database schema updated successfully!' . PHP_EOL);
} else {
$output->writeln('<comment>ATTENTION</comment>: This operation should not be executed in a production environment.');
$output->writeln(' Use the incremental update to detect changes during development and use');
$output->writeln(' the SQL DDL provided to manually update your database in production.');
$output->writeln('');
$output->write('ATTENTION: This operation should not be executed in an production enviroment.' . PHP_EOL);
$output->write('Use the incremental update to detect changes during development and use' . PHP_EOL);
$output->write('this SQL DDL to manually update your database in production.' . PHP_EOL . PHP_EOL);
$output->writeln(sprintf('The Schema-Tool would execute <info>"%s"</info> queries to update the database.', count($sqls)));
$output->writeln('Please run the operation by passing one of the following options:');
$output->writeln(sprintf(' <info>%s --force</info> to execute the command', $this->getName()));
$output->writeln(sprintf(' <info>%s --dump-sql</info> to dump the SQL statements to the screen', $this->getName()));
$sqls = $schemaTool->getUpdateSchemaSql($metadatas, $saveMode);
if (count($sqls)) {
$output->write('Schema-Tool would execute ' . count($sqls) . ' queries to update the database.' . PHP_EOL);
$output->write('Please run the operation with --force to execute these queries or use --dump-sql to see them.' . PHP_EOL);
} else {
$output->write('Nothing to update. The database is in sync with the current entity metadata.' . PHP_EOL);
}
}
}
}
@@ -64,7 +64,6 @@ class ConsoleRunner
new \Doctrine\ORM\Tools\Console\Command\ConvertMappingCommand(),
new \Doctrine\ORM\Tools\Console\Command\RunDqlCommand(),
new \Doctrine\ORM\Tools\Console\Command\ValidateSchemaCommand(),
new \Doctrine\ORM\Tools\Console\Command\InfoCommand()
));
}
}
@@ -52,17 +52,6 @@ class DisconnectedClassMetadataFactory extends ClassMetadataFactory
return $metadata;
}
/**
* Validate runtime metadata is correctly defined.
*
* @param ClassMetadata $class
* @param ClassMetadata $parent
*/
protected function validateRuntimeMetadata($class, $parent)
{
// validate nothing
}
/**
* @override
*/
+16 -50
View File
@@ -91,8 +91,6 @@ class EntityGenerator
<namespace>
use Doctrine\ORM\Mapping as ORM;
<entityAnnotation>
<entityClassName>
{
@@ -103,7 +101,7 @@ use Doctrine\ORM\Mapping as ORM;
'/**
* <description>
*
* @return <variableType>
* @return <variableType>$<variableName>
*/
public function <methodName>()
{
@@ -148,18 +146,11 @@ public function <methodName>()
}
';
public function __construct()
{
if (version_compare(\Doctrine\Common\Version::VERSION, '3.0.0-DEV', '>=')) {
$this->_annotationsPrefix = 'ORM\\';
}
}
/**
* Generate and write entity classes for the given array of ClassMetadataInfo instances
*
* @param array $metadatas
* @param string $outputDirectory
* @param string $outputDirectory
* @return void
*/
public function generate(array $metadatas, $outputDirectory)
@@ -173,7 +164,7 @@ public function <methodName>()
* Generated and write entity class to disk for the given ClassMetadataInfo instance
*
* @param ClassMetadataInfo $metadata
* @param string $outputDirectory
* @param string $outputDirectory
* @return void
*/
public function writeEntityClass(ClassMetadataInfo $metadata, $outputDirectory)
@@ -210,7 +201,7 @@ public function <methodName>()
/**
* Generate a PHP5 Doctrine 2 entity class from the given ClassMetadataInfo instance
*
* @param ClassMetadataInfo $metadata
* @param ClassMetadataInfo $metadata
* @return string $code
*/
public function generateEntityClass(ClassMetadataInfo $metadata)
@@ -236,8 +227,8 @@ public function <methodName>()
/**
* Generate the updated code for the given ClassMetadataInfo and entity at path
*
* @param ClassMetadataInfo $metadata
* @param string $path
* @param ClassMetadataInfo $metadata
* @param string $path
* @return string $code;
*/
public function generateUpdatedEntityClass(ClassMetadataInfo $metadata, $path)
@@ -254,7 +245,7 @@ public function <methodName>()
/**
* Set the number of spaces the exported class should have
*
* @param integer $numSpaces
* @param integer $numSpaces
* @return void
*/
public function setNumSpaces($numSpaces)
@@ -266,7 +257,7 @@ public function <methodName>()
/**
* Set the extension to use when writing php files to disk
*
* @param string $extension
* @param string $extension
* @return void
*/
public function setExtension($extension)
@@ -287,7 +278,7 @@ public function <methodName>()
/**
* Set whether or not to generate annotations for the entity
*
* @param bool $bool
* @param bool $bool
* @return void
*/
public function setGenerateAnnotations($bool)
@@ -302,16 +293,13 @@ public function <methodName>()
*/
public function setAnnotationPrefix($prefix)
{
if (version_compare(\Doctrine\Common\Version::VERSION, '3.0.0-DEV', '>=')) {
return;
}
$this->_annotationsPrefix = $prefix;
}
/**
* Set whether or not to try and update the entity if it already exists
*
* @param bool $bool
* @param bool $bool
* @return void
*/
public function setUpdateEntityIfExists($bool)
@@ -419,7 +407,7 @@ public function <methodName>()
$tokens = token_get_all($src);
$lastSeenNamespace = "";
$lastSeenClass = false;
$inNamespace = false;
$inClass = false;
for ($i = 0; $i < count($tokens); $i++) {
@@ -438,7 +426,7 @@ public function <methodName>()
if ($inClass) {
$inClass = false;
$lastSeenClass = $lastSeenNamespace . ($lastSeenNamespace ? '\\' : '') . $token[1];
$lastSeenClass = $lastSeenNamespace . '\\' . $token[1];
$this->_staticReflection[$lastSeenClass]['properties'] = array();
$this->_staticReflection[$lastSeenClass]['methods'] = array();
}
@@ -462,14 +450,6 @@ public function <methodName>()
private function _hasProperty($property, ClassMetadataInfo $metadata)
{
if ($this->_extendsClass()) {
// don't generate property if its already on the base class.
$reflClass = new \ReflectionClass($this->_getClassToExtend());
if ($reflClass->hasProperty($property)) {
return true;
}
}
return (
isset($this->_staticReflection[$metadata->name]) &&
in_array($property, $this->_staticReflection[$metadata->name]['properties'])
@@ -478,14 +458,6 @@ public function <methodName>()
private function _hasMethod($method, ClassMetadataInfo $metadata)
{
if ($this->_extendsClass()) {
// don't generate method if its already on the base class.
$reflClass = new \ReflectionClass($this->_getClassToExtend());
if ($reflClass->hasMethod($method)) {
return true;
}
}
return (
isset($this->_staticReflection[$metadata->name]) &&
in_array($method, $this->_staticReflection[$metadata->name]['methods'])
@@ -702,13 +674,7 @@ public function <methodName>()
private function _generateEntityStubMethod(ClassMetadataInfo $metadata, $type, $fieldName, $typeHint = null)
{
if ($type == "add") {
$addMethod = explode("\\", $typeHint);
$addMethod = end($addMethod);
$methodName = $type . $addMethod;
} else {
$methodName = $type . Inflector::classify($fieldName);
}
$methodName = $type . Inflector::classify($fieldName);
if ($this->_hasMethod($methodName, $metadata)) {
return;
@@ -783,7 +749,7 @@ public function <methodName>()
}
if (isset($joinColumn['onDelete'])) {
$joinColumnAnnot[] = 'onDelete="' . ($joinColumn['onDelete'] . '"');
$joinColumnAnnot[] = 'onDelete=' . ($joinColumn['onDelete'] ? 'true' : 'false');
}
if (isset($joinColumn['onUpdate'])) {
@@ -844,7 +810,7 @@ public function <methodName>()
if ($associationMapping['isCascadeMerge']) $cascades[] = '"merge"';
if ($associationMapping['isCascadeRefresh']) $cascades[] = '"refresh"';
$typeOptions[] = 'cascade={' . implode(',', $cascades) . '}';
$typeOptions[] = 'cascade={' . implode(',', $cascades) . '}';
}
if (isset($associationMapping['orphanRemoval']) && $associationMapping['orphanRemoval']) {
@@ -898,7 +864,7 @@ public function <methodName>()
$lines[] = $this->_spaces . ' * @' . $this->_annotationsPrefix . 'OrderBy({';
foreach ($associationMapping['orderBy'] as $name => $direction) {
$lines[] = $this->_spaces . ' * "' . $name . '"="' . $direction . '",';
$lines[] = $this->_spaces . ' * "' . $name . '"="' . $direction . '",';
}
$lines[count($lines) - 1] = substr($lines[count($lines) - 1], 0, strlen($lines[count($lines) - 1]) - 1);
@@ -27,7 +27,7 @@ use Doctrine\ORM\Tools\Export\ExportException;
/**
* Abstract base class which is to be used for the Exporter drivers
* which can be found in \Doctrine\ORM\Tools\Export\Driver
* which can be found in Doctrine\ORM\Tools\Export\Driver
*
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link www.doctrine-project.org
@@ -120,30 +120,22 @@ class PhpExporter extends AbstractExporter
$associationMappingArray = array_merge($associationMappingArray, $oneToOneMappingArray);
} else if ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) {
$method = 'mapOneToMany';
$potentialAssociationMappingIndexes = array(
'mappedBy',
'orphanRemoval',
'orderBy',
$method = 'mapOneToMany';
$oneToManyMappingArray = array(
'mappedBy' => $associationMapping['mappedBy'],
'orphanRemoval' => $associationMapping['orphanRemoval'],
'orderBy' => $associationMapping['orderBy']
);
foreach ($potentialAssociationMappingIndexes as $index) {
if (isset($associationMapping[$index])) {
$oneToManyMappingArray[$index] = $associationMapping[$index];
}
}
$associationMappingArray = array_merge($associationMappingArray, $oneToManyMappingArray);
} else if ($associationMapping['type'] == ClassMetadataInfo::MANY_TO_MANY) {
$method = 'mapManyToMany';
$potentialAssociationMappingIndexes = array(
'mappedBy',
'joinTable',
'orderBy',
$method = 'mapManyToMany';
$manyToManyMappingArray = array(
'mappedBy' => $associationMapping['mappedBy'],
'joinTable' => $associationMapping['joinTable'],
'orderBy' => $associationMapping['orderBy']
);
foreach ($potentialAssociationMappingIndexes as $index) {
if (isset($associationMapping[$index])) {
$manyToManyMappingArray[$index] = $associationMapping[$index];
}
}
$associationMappingArray = array_merge($associationMappingArray, $manyToManyMappingArray);
}
@@ -43,7 +43,7 @@ class YamlExporter extends AbstractExporter
*
* TODO: Should this code be pulled out in to a toArray() method in ClassMetadata
*
* @param ClassMetadataInfo $metadata
* @param ClassMetadataInfo $metadata
* @return mixed $exported
*/
public function exportClassMetadata(ClassMetadataInfo $metadata)
@@ -84,9 +84,9 @@ class YamlExporter extends AbstractExporter
if (isset($metadata->table['uniqueConstraints'])) {
$array['uniqueConstraints'] = $metadata->table['uniqueConstraints'];
}
$fieldMappings = $metadata->fieldMappings;
$ids = array();
foreach ($fieldMappings as $name => $fieldMapping) {
$fieldMapping['column'] = $fieldMapping['columnName'];
@@ -94,7 +94,7 @@ class YamlExporter extends AbstractExporter
$fieldMapping['columnName'],
$fieldMapping['fieldName']
);
if ($fieldMapping['column'] == $name) {
unset($fieldMapping['column']);
}
@@ -111,7 +111,7 @@ class YamlExporter extends AbstractExporter
if ($idGeneratorType = $this->_getIdGeneratorTypeString($metadata->generatorType)) {
$ids[$metadata->getSingleIdentifierFieldName()]['generator']['strategy'] = $this->_getIdGeneratorTypeString($metadata->generatorType);
}
if ($ids) {
$array['fields'] = $ids;
}
@@ -145,7 +145,7 @@ class YamlExporter extends AbstractExporter
'targetEntity' => $associationMapping['targetEntity'],
'cascade' => $cascade,
);
if ($associationMapping['type'] & ClassMetadataInfo::TO_ONE) {
$joinColumns = $associationMapping['joinColumns'];
$newJoinColumns = array();
@@ -164,7 +164,7 @@ class YamlExporter extends AbstractExporter
'joinColumns' => $newJoinColumns,
'orphanRemoval' => $associationMapping['orphanRemoval'],
);
$associationMappingArray = array_merge($associationMappingArray, $oneToOneMappingArray);
$array['oneToOne'][$name] = $associationMappingArray;
} else if ($associationMapping['type'] == ClassMetadataInfo::ONE_TO_MANY) {
@@ -172,7 +172,7 @@ class YamlExporter extends AbstractExporter
'mappedBy' => $associationMapping['mappedBy'],
'inversedBy' => $associationMapping['inversedBy'],
'orphanRemoval' => $associationMapping['orphanRemoval'],
'orderBy' => isset($associationMapping['orderBy']) ? $associationMapping['orderBy'] : null
'orderBy' => $associationMapping['orderBy']
);
$associationMappingArray = array_merge($associationMappingArray, $oneToManyMappingArray);
@@ -181,10 +181,10 @@ class YamlExporter extends AbstractExporter
$manyToManyMappingArray = array(
'mappedBy' => $associationMapping['mappedBy'],
'inversedBy' => $associationMapping['inversedBy'],
'joinTable' => isset($associationMapping['joinTable']) ? $associationMapping['joinTable'] : null,
'orderBy' => isset($associationMapping['orderBy']) ? $associationMapping['orderBy'] : null
'joinTable' => $associationMapping['joinTable'],
'orderBy' => isset($associationMapping['orderBy']) ? $associationMapping['orderBy'] : null
);
$associationMappingArray = array_merge($associationMappingArray, $manyToManyMappingArray);
$array['manyToMany'][$name] = $associationMappingArray;
}
+19 -71
View File
@@ -56,7 +56,7 @@ class SchemaTool
* Initializes a new SchemaTool instance that uses the connection of the
* provided EntityManager.
*
* @param \Doctrine\ORM\EntityManager $em
* @param Doctrine\ORM\EntityManager $em
*/
public function __construct(EntityManager $em)
{
@@ -174,7 +174,7 @@ class SchemaTool
$discrColumnDef = $this->_getDiscriminatorColumnDefinition($class, $table);
} else {
// Add an ID FK column to child tables
/* @var \Doctrine\ORM\Mapping\ClassMetadata $class */
/* @var Doctrine\ORM\Mapping\ClassMetadata $class */
$idMapping = $class->fieldMappings[$class->identifier[0]];
$this->_gatherColumn($class, $idMapping, $table);
$columnName = $class->getQuotedColumnName($class->identifier[0], $this->_platform);
@@ -199,22 +199,6 @@ class SchemaTool
$this->_gatherRelationsSql($class, $table, $schema);
}
$pkColumns = array();
foreach ($class->identifier AS $identifierField) {
if (isset($class->fieldMappings[$identifierField])) {
$pkColumns[] = $class->getQuotedColumnName($identifierField, $this->_platform);
} else if (isset($class->associationMappings[$identifierField])) {
/* @var $assoc \Doctrine\ORM\Mapping\OneToOne */
$assoc = $class->associationMappings[$identifierField];
foreach ($assoc['joinColumns'] AS $joinColumn) {
$pkColumns[] = $joinColumn['name'];
}
}
}
if (!$table->hasIndex('primary')) {
$table->setPrimaryKey($pkColumns);
}
if (isset($class->table['indexes'])) {
foreach ($class->table['indexes'] AS $indexName => $indexData) {
$table->addIndex($indexData['columns'], $indexName);
@@ -301,11 +285,10 @@ class SchemaTool
$pkColumns[] = $class->getQuotedColumnName($mapping['fieldName'], $this->_platform);
}
}
// For now, this is a hack required for single table inheritence, since this method is called
// twice by single table inheritence relations
if(!$table->hasIndex('primary')) {
//$table->setPrimaryKey($pkColumns);
$table->setPrimaryKey($pkColumns);
}
return $columns;
@@ -426,47 +409,13 @@ class SchemaTool
}
}
/**
* Get 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 recursivly 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 array($class, $referencedFieldName);
} else 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;
}
/**
* Gather columns and fk constraints that are required for one part of relationship.
*
* @param array $joinColumns
* @param \Doctrine\DBAL\Schema\Table $theJoinTable
* @param ClassMetadata $class
* @param array $mapping
* @param \Doctrine\ORM\Mapping\AssociationMapping $mapping
* @param array $primaryKeyColumns
* @param array $uniqueConstraints
*/
@@ -479,9 +428,9 @@ class SchemaTool
foreach ($joinColumns as $joinColumn) {
$columnName = $joinColumn['name'];
list($definingClass, $referencedFieldName) = $this->getDefiningClass($class, $joinColumn['referencedColumnName']);
$referencedFieldName = $class->getFieldName($joinColumn['referencedColumnName']);
if (!$definingClass) {
if ( ! $class->hasField($referencedFieldName)) {
throw new \Doctrine\ORM\ORMException(
"Column name `".$joinColumn['referencedColumnName']."` referenced for relation from ".
$mapping['sourceEntity'] . " towards ". $mapping['targetEntity'] . " does not exist."
@@ -497,7 +446,7 @@ class SchemaTool
// It might exist already if the foreign key is mapped into a regular
// property as well.
$fieldMapping = $definingClass->getFieldMapping($referencedFieldName);
$fieldMapping = $class->getFieldMapping($referencedFieldName);
$columnDef = null;
if (isset($joinColumn['columnDefinition'])) {
@@ -516,7 +465,9 @@ class SchemaTool
$columnOptions['precision'] = $fieldMapping['precision'];
}
$theJoinTable->addColumn($columnName, $fieldMapping['type'], $columnOptions);
$theJoinTable->addColumn(
$columnName, $class->getTypeOfColumn($joinColumn['referencedColumnName']), $columnOptions
);
}
if (isset($joinColumn['unique']) && $joinColumn['unique'] == true) {
@@ -626,12 +577,14 @@ class SchemaTool
}
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));
foreach ($table->getIndexes() AS $index) {
if ($index->isPrimary()) {
$columns = $index->getColumns();
if (count($columns) == 1) {
$checkSequence = $table->getName() . "_" . $columns[0] . "_seq";
if ($fullSchema->hasSequence($checkSequence)) {
$visitor->acceptSequence($fullSchema->getSequence($checkSequence));
}
}
}
}
@@ -643,11 +596,9 @@ class SchemaTool
/**
* Updates the database schema of the given classes by comparing the ClassMetadata
* instances to the current database schema that is inspected. If $saveMode is set
* to true the command is executed in the Database, else SQL is returned.
* ins$tableNametances to the current database schema that is inspected.
*
* @param array $classes
* @param boolean $saveMode
* @return void
*/
public function updateSchema(array $classes, $saveMode=false)
@@ -663,11 +614,8 @@ class SchemaTool
/**
* 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.
* If $saveMode is set to true the command is executed in the Database,
* else SQL is returned.
*
* @param array $classes The classes to consider.
* @param boolean $saveMode True for writing to DB, false for SQL string
* @return array The sequence of SQL statements.
*/
public function getUpdateSchemaSql(array $classes, $saveMode=false)
+1 -1
View File
@@ -214,6 +214,6 @@ class SchemaValidator
$schemaTool = new SchemaTool($this->em);
$allMetadata = $this->em->getMetadataFactory()->getAllMetadata();
return (count($schemaTool->getUpdateSchemaSql($allMetadata, true)) == 0);
return (count($schemaTool->getUpdateSchemaSql($allMetadata, false)) == 0);
}
}
-194
View File
@@ -1,194 +0,0 @@
<?php
/*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* This software consists of voluntary contributions made by many individuals
* and is licensed under the LGPL. For more information, see
* <http://www.doctrine-project.org>.
*/
namespace Doctrine\ORM\Tools;
use Doctrine\Common\ClassLoader;
use Doctrine\Common\Cache\Cache;
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 <kontakt@beberlei.de>
*/
class Setup
{
/**
* Use this method to register all autoloaders for a setup where Doctrine is checked out from
* its github repository at {@link http://github.com/doctrine/doctrine2}
*
* @param string $gitCheckoutRootPath
* @return void
*/
static public function registerAutoloadGit($gitCheckoutRootPath)
{
if (!class_exists('Doctrine\Common\ClassLoader', false)) {
require_once $gitCheckoutRootPath . "/lib/vendor/doctrine-common/lib/Doctrine/Common/ClassLoader.php";
}
$loader = new ClassLoader("Doctrine\Common", $gitCheckoutRootPath . "/lib/vendor/doctrine-common/lib");
$loader->register();
$loader = new ClassLoader("Doctrine\DBAL", $gitCheckoutRootPath . "/lib/vendor/doctrine-dbal/lib");
$loader->register();
$loader = new ClassLoader("Doctrine\ORM", $gitCheckoutRootPath . "/lib");
$loader->register();
$loader = new ClassLoader("Symfony\Component", $gitCheckoutRootPath . "/lib/vendor");
$loader->register();
}
/**
* Use this method to register all autoloaders for a setup where Doctrine is installed
* though {@link http://pear.doctrine-project.org}.
*
* @return void
*/
static public function registerAutoloadPEAR()
{
if (!class_exists('Doctrine\Common\ClassLoader', false)) {
require_once "Doctrine/Common/ClassLoader.php";
}
$loader = new ClassLoader("Doctrine");
$loader->register();
$parts = explode(PATH_SEPARATOR, get_include_path());
foreach ($parts AS $includePath) {
if ($includePath != "." && file_exists($includePath . "/Doctrine")) {
$loader = new ClassLoader("Symfony\Component", $includePath . "/Doctrine");
$loader->register();
return;
}
}
}
/**
* Use this method to register all autoloads for a downloaded Doctrine library.
* Pick the directory the library was uncompressed into.
*
* @param string $directory
*/
static public 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();
}
/**
* Create a configuration with an annotation metadata driver.
*
* @param array $paths
* @param boolean $isDevMode
* @param string $proxyDir
* @param Cache $cache
* @return Configuration
*/
static public function createAnnotationMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null)
{
$config = self::createConfiguration($isDevMode, $proxyDir, $cache);
$config->setMetadataDriverImpl($config->newDefaultAnnotationDriver($paths));
return $config;
}
/**
* Create a configuration with an annotation metadata driver.
*
* @param array $paths
* @param boolean $isDevMode
* @param string $proxyDir
* @param Cache $cache
* @return Configuration
*/
static public function createXMLMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null)
{
$config = self::createConfiguration($isDevMode, $proxyDir, $cache);
$config->setMetadataDriverImpl(new XmlDriver($paths));
return $config;
}
/**
* Create a configuration with an annotation metadata driver.
*
* @param array $paths
* @param boolean $isDevMode
* @param string $proxyDir
* @param Cache $cache
* @return Configuration
*/
static public function createYAMLMetadataConfiguration(array $paths, $isDevMode = false, $proxyDir = null, Cache $cache = null)
{
$config = self::createConfiguration($isDevMode, $proxyDir, $cache);
$config->setMetadataDriverImpl(new YamlDriver($paths));
return $config;
}
/**
* Create a configuration without a metadata driver.
*
* @param bool $isDevMode
* @param string $proxyDir
* @param Cache $cache
* @return Configuration
*/
static public function createConfiguration($isDevMode = false, $proxyDir = null, Cache $cache = null)
{
$proxyDir = $proxyDir ?: sys_get_temp_dir();
if ($isDevMode === false && $cache === null) {
if (extension_loaded('apc')) {
$cache = new \Doctrine\Common\Cache\ApcCache;
} else if (extension_loaded('xcache')) {
$cache = new \Doctrine\Common\Cache\XcacheCache;
} else if (extension_loaded('memcache')) {
$memcache = new \Memcache();
$memcache->connect('127.0.0.1');
$cache = new \Doctrine\Common\Cache\MemcacheCache();
$cache->setMemcache($memcache);
} else {
$cache = new ArrayCache;
}
} else if ($cache === null) {
$cache = new ArrayCache;
}
$cache->setNamespace("dc2_" . md5($proxyDir) . "_"); // to avoid collisions
$config = new Configuration();
$config->setMetadataCacheImpl($cache);
$config->setQueryCacheImpl($cache);
$config->setResultCacheImpl($cache);
$config->setProxyDir( $proxyDir );
$config->setProxyNamespace('DoctrineProxies');
$config->setAutoGenerateProxyClasses($isDevMode);
return $config;
}
}
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -36,7 +36,7 @@ class Version
/**
* Current Doctrine Version
*/
const VERSION = '2.1.5';
const VERSION = '2.0.7';
/**
* Compares a Doctrine version with the current one.
-59
View File
@@ -1,59 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Use this configuration file as a template to run the tests against any dbms.
Procedure:
1) Save a copy of this file with a name of your chosing. It doesn't matter
where you place it as long as you know where it is.
i.e. "mysqlconf.xml" (It needs the ending .xml).
2) Edit the file and fill in your settings (database name, type, username, etc.)
Just change the "value"s, not the names of the var elements.
3) To run the tests against the database type the following from within the
tests/ folder: phpunit -c <filename> ...
Example: phpunit -c mysqlconf.xml AllTests
-->
<phpunit backupGlobals="false"
backupStaticAttributes="false"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false"
syntaxCheck="false"
bootstrap="./tests/Doctrine/Tests/TestInit.php"
>
<testsuites>
<testsuite name="Doctrine ORM Test Suite">
<directory>./tests/Doctrine/Tests/ORM</directory>
</testsuite>
</testsuites>
<groups>
<exclude>
<group>performance</group>
<group>locking_functional</group>
</exclude>
</groups>
<php>
<!-- "Real" test database -->
<!-- uncomment, otherwise sqlite memory runs
<var name="db_type" value="pdo_mysql"/>
<var name="db_host" value="localhost" />
<var name="db_username" value="root" />
<var name="db_password" value="" />
<var name="db_name" value="doctrine_tests" />
<var name="db_port" value="3306"/>-->
<!--<var name="db_event_subscribers" value="Doctrine\DBAL\Event\Listeners\OracleSessionInit">-->
<!-- Database for temporary connections (i.e. to drop/create the main database) -->
<var name="tmpdb_type" value="pdo_mysql"/>
<var name="tmpdb_host" value="localhost" />
<var name="tmpdb_username" value="root" />
<var name="tmpdb_password" value="" />
<var name="tmpdb_name" value="doctrine_tests_tmp" />
<var name="tmpdb_port" value="3306"/>
</php>
</phpunit>
-21
View File
@@ -1,21 +0,0 @@
#!/bin/bash
# This script is a small convenience wrapper for running the doctrine testsuite against a large bunch of databases.
# Just create the phpunit.xmls as described in the array below and configure the specific files <php /> section
# to connect to that database. Just omit a file if you dont have that database and the tests will be skipped.
configs[1]="mysql.phpunit.xml"
configs[2]='postgres.phpunit.xml'
configs[3]='sqlite.phpunit.xml'
configs[4]='oracle.phpunit.xml'
configs[5]='db2.phpunit.xml'
configs[6]='pdo-ibm.phpunit.xml'
configs[7]='sqlsrv.phpunit.xml'
for i in "${configs[@]}"; do
if [ -f "$i" ];
then
echo "RUNNING TESTS WITH CONFIG $i"
phpunit -c "$i" "$@"
fi;
done
+33
View File
@@ -0,0 +1,33 @@
<?php
namespace Doctrine\Tests;
use Doctrine\Tests\Common;
use Doctrine\Tests\ORM;
use Doctrine\Tests\DBAL;
if (!defined('PHPUnit_MAIN_METHOD')) {
define('PHPUnit_MAIN_METHOD', 'AllTests::main');
}
require_once __DIR__ . '/TestInit.php';
class AllTests
{
public static function main()
{
\PHPUnit_TextUI_TestRunner::run(self::suite());
}
public static function suite()
{
$suite = new DoctrineTestSuite('Doctrine Tests');
$suite->addTest(ORM\AllTests::suite());
return $suite;
}
}
if (PHPUnit_MAIN_METHOD == 'AllTests::main') {
AllTests::main();
}
@@ -0,0 +1,19 @@
<?php
namespace Doctrine\Tests;
class DbalFunctionalTestSuite extends DbalTestSuite
{
protected function setUp()
{
if ( ! isset($this->sharedFixture['conn'])) {
$this->sharedFixture['conn'] = TestUtil::getConnection();
}
}
protected function tearDown()
{
$this->sharedFixture['conn']->close();
$this->sharedFixture = null;
}
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace Doctrine\Tests;
/**
* The outermost test suite for all dbal related testcases & suites.
*/
class DbalTestSuite extends DoctrineTestSuite
{
}
@@ -0,0 +1,11 @@
<?php
namespace Doctrine\Tests;
/**
* Doctrine's basic test suite implementation. Provides functionality needed by all
* test suites.
*/
class DoctrineTestSuite extends \PHPUnit_Framework_TestSuite
{
}
@@ -78,7 +78,7 @@ class EntityManagerMock extends \Doctrine\ORM\EntityManager
$config = new \Doctrine\ORM\Configuration();
$config->setProxyDir(__DIR__ . '/../Proxies');
$config->setProxyNamespace('Doctrine\Tests\Proxies');
$config->setMetadataDriverImpl($config->newDefaultAnnotationDriver());
$config->setMetadataDriverImpl(\Doctrine\ORM\Mapping\Driver\AnnotationDriver::create());
}
if (is_null($eventManager)) {
$eventManager = new \Doctrine\Common\EventManager();
@@ -59,7 +59,7 @@ class EntityPersisterMock extends \Doctrine\ORM\Persisters\BasicEntityPersister
$this->_updates[] = $entity;
}
public function exists($entity, array $extraConditions = array())
public function exists($entity)
{
$this->existsCalled = true;
}
+1 -4
View File
@@ -7,9 +7,6 @@ use Doctrine\Common\Collections\ArrayCollection;
/**
* @Entity
* @Table(name="cms_users")
* @NamedQueries({
* @NamedQuery(name="all", query="SELECT u FROM __CLASS__ u")
* })
*/
class CmsUser
{
@@ -31,7 +28,7 @@ class CmsUser
*/
public $name;
/**
* @OneToMany(targetEntity="CmsPhonenumber", mappedBy="user", cascade={"persist", "merge"}, orphanRemoval=true)
* @OneToMany(targetEntity="CmsPhonenumber", mappedBy="user", cascade={"persist", "remove", "merge"}, orphanRemoval=true)
*/
public $phonenumbers;
/**
@@ -7,11 +7,7 @@ namespace Doctrine\Tests\Models\Company;
* @Table(name="company_contracts")
* @InheritanceType("SINGLE_TABLE")
* @DiscriminatorColumn(name="discr", type="string")
* @DiscriminatorMap({
* "fix" = "CompanyFixContract",
* "flexible" = "CompanyFlexContract",
* "flexultra" = "CompanyFlexUltraContract"
* })
* @DiscriminatorMap({"fix" = "CompanyFixContract", "flexible" = "CompanyFlexContract", "flexultra" = "CompanyFlexUltraContract"})
*/
abstract class CompanyContract
{
@@ -17,11 +17,6 @@ class CompanyEmployee extends CompanyPerson
* @Column(type="string", length=255)
*/
private $department;
/**
* @Column(type="datetime", nullable=true)
*/
private $startDate;
public function getSalary() {
return $this->salary;
@@ -38,12 +33,4 @@ class CompanyEmployee extends CompanyPerson
public function setDepartment($dep) {
$this->department = $dep;
}
public function getStartDate() {
return $this->startDate;
}
public function setStartDate($date) {
$this->startDate = $date;
}
}
@@ -1,65 +0,0 @@
<?php
namespace Doctrine\Tests\Models\DDC117;
/**
* @Entity
*/
class DDC117ApproveChanges
{
/**
* @Id @Column(type="integer") @GeneratedValue
*/
private $id;
/**
* @ManyToOne(targetEntity="DDC117ArticleDetails")
* @JoinColumn(name="details_id", referencedColumnName="article_id")
*/
private $articleDetails;
/**
* @ManyToOne(targetEntity="DDC117Reference")
* @JoinColumns({
* @JoinColumn(name="source_id", referencedColumnName="source_id"),
* @JoinColumn(name="target_id", referencedColumnName="target_id")
* })
*/
private $reference;
/**
* @ManyToOne(targetEntity="DDC117Translation")
* @JoinColumns({
* @JoinColumn(name="trans_article_id", referencedColumnName="article_id"),
* @JoinColumn(name="trans_language", referencedColumnName="language")
* })
*/
private $translation;
public function __construct($details, $reference, $translation)
{
$this->articleDetails = $details;
$this->reference = $reference;
$this->translation = $translation;
}
public function getId()
{
return $this->id;
}
public function getArticleDetails()
{
return $this->articleDetails;
}
public function getReference()
{
return $this->reference;
}
public function getTranslation()
{
return $this->translation;
}
}

Some files were not shown because too many files have changed in this diff Show More