mirror of
https://github.com/doctrine/orm.git
synced 2026-03-24 15:02:22 +01:00
Compare commits
1729 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b5e19dca18 | ||
|
|
585c9fd208 | ||
|
|
c6101317cd | ||
|
|
477642a171 | ||
|
|
75e968b250 | ||
|
|
3294900faa | ||
|
|
2353736e8f | ||
|
|
586aea0236 | ||
|
|
18a7fc5726 | ||
|
|
44a56e8e49 | ||
|
|
c2b82fa529 | ||
|
|
d7da012918 | ||
|
|
85e5398354 | ||
|
|
3fd8392ccf | ||
|
|
0da0d02dec | ||
|
|
387516f144 | ||
|
|
53e164ba5d | ||
|
|
4d9f24b2ee | ||
|
|
a96bbbbe0a | ||
|
|
8edecfdcad | ||
|
|
741080dc17 | ||
|
|
30ad1b0706 | ||
|
|
9cdee12ccf | ||
|
|
c76280be42 | ||
|
|
0dcfabbc4d | ||
|
|
366c6a7dd6 | ||
|
|
2597192f22 | ||
|
|
bbf527a273 | ||
|
|
9308afc9a5 | ||
|
|
1a81444b04 | ||
|
|
d181fbc98d | ||
|
|
114e233d87 | ||
|
|
bdb36a71c5 | ||
|
|
8c1d64372c | ||
|
|
f4ba58358c | ||
|
|
131d3003a0 | ||
|
|
48e94343fd | ||
|
|
9d909cd583 | ||
|
|
3aaa90e1a8 | ||
|
|
ece6a005bc | ||
|
|
641af15280 | ||
|
|
971865f271 | ||
|
|
af08f05164 | ||
|
|
2e6b50bb53 | ||
|
|
185b4e0c41 | ||
|
|
5c585b4c02 | ||
|
|
787a208708 | ||
|
|
f8a582d454 | ||
|
|
72ce9a7f37 | ||
|
|
04de52d4c9 | ||
|
|
17862d9a2a | ||
|
|
c99c7b6694 | ||
|
|
104a76a6b1 | ||
|
|
79a04b295f | ||
|
|
3f2ddc60d4 | ||
|
|
3b3d762277 | ||
|
|
992b51eba7 | ||
|
|
5527e121ec | ||
|
|
c55394c616 | ||
|
|
1676cf23c0 | ||
|
|
6dd3078153 | ||
|
|
00a5f18544 | ||
|
|
1e2eca1a7e | ||
|
|
7029d3738d | ||
|
|
7f68347c1f | ||
|
|
e63575ea18 | ||
|
|
e8d3fc73ff | ||
|
|
7c1235dedb | ||
|
|
d7bdae3bbb | ||
|
|
e2c40dc365 | ||
|
|
dfa6ff64c4 | ||
|
|
bcbef5670c | ||
|
|
354fa14df4 | ||
|
|
afd8ea91e3 | ||
|
|
ef27721db2 | ||
|
|
13d32e6de5 | ||
|
|
bd1e6ac309 | ||
|
|
14bd794960 | ||
|
|
369a30ad3d | ||
|
|
cebb820030 | ||
|
|
ac9df05c92 | ||
|
|
04e6cc78cd | ||
|
|
2158a0788e | ||
|
|
fc4a07c2b3 | ||
|
|
2389f77d91 | ||
|
|
1eaa822d2a | ||
|
|
9dd3b66fe6 | ||
|
|
1369e3d133 | ||
|
|
50dac4096a | ||
|
|
aa0cb0b6d7 | ||
|
|
5b55739990 | ||
|
|
3e53d9d79c | ||
|
|
619d29adb2 | ||
|
|
68adc7fed3 | ||
|
|
98c4833afc | ||
|
|
e5979b5ef2 | ||
|
|
fb3c6f0e8f | ||
|
|
5b3eee8071 | ||
|
|
81f97e92d3 | ||
|
|
93cef61270 | ||
|
|
a723b73929 | ||
|
|
34ac207b3c | ||
|
|
c8fcd3f8a5 | ||
|
|
a0ba420969 | ||
|
|
816f709950 | ||
|
|
e0455b5550 | ||
|
|
fcff39571f | ||
|
|
51cd553de8 | ||
|
|
75276e453e | ||
|
|
a2e00a96cc | ||
|
|
915da58fb7 | ||
|
|
f3aae5de0e | ||
|
|
01f058953b | ||
|
|
e2c1d7c38a | ||
|
|
113c6f51c2 | ||
|
|
b2385e0afa | ||
|
|
4aafeaf7a6 | ||
|
|
fe292cc503 | ||
|
|
3b04cf5b2f | ||
|
|
f3f1091b44 | ||
|
|
6e924f2a2c | ||
|
|
346e34adf6 | ||
|
|
245d906ebf | ||
|
|
eaae1f222f | ||
|
|
b67140f73c | ||
|
|
7c2e5ae5b2 | ||
|
|
fc00d5f39f | ||
|
|
86dbddd596 | ||
|
|
5adc8bec58 | ||
|
|
baae40c5f4 | ||
|
|
7b758eee57 | ||
|
|
18d4a2f970 | ||
|
|
3bdf86922c | ||
|
|
3783ca6b43 | ||
|
|
ff2c5f85c3 | ||
|
|
58a2cba6da | ||
|
|
45df16cdc6 | ||
|
|
2dd2d694ca | ||
|
|
8c24e528ad | ||
|
|
8d0f49f227 | ||
|
|
996e47bf61 | ||
|
|
0a95e42ea8 | ||
|
|
82e1d7fa80 | ||
|
|
12cddf20e3 | ||
|
|
cc4613533b | ||
|
|
4bfdcd32f7 | ||
|
|
6ba205f561 | ||
|
|
6093017bc6 | ||
|
|
64904c77c1 | ||
|
|
632d13ba0c | ||
|
|
fe11831bd7 | ||
|
|
63580dfe26 | ||
|
|
076663fe3a | ||
|
|
1023af6a1f | ||
|
|
da331cd277 | ||
|
|
30e86f442f | ||
|
|
5cdb0ae8be | ||
|
|
379e69865e | ||
|
|
97d7cae012 | ||
|
|
f6381d7b76 | ||
|
|
94714db132 | ||
|
|
e522391ee9 | ||
|
|
943cff673a | ||
|
|
63fbf7c2e5 | ||
|
|
737b74e5d5 | ||
|
|
01b1b0b5fb | ||
|
|
5c05a4356a | ||
|
|
245718c9eb | ||
|
|
e9e36dcf32 | ||
|
|
905acf9176 | ||
|
|
5b97357402 | ||
|
|
abd3ddc1b1 | ||
|
|
ccace8cb8b | ||
|
|
03fb734de8 | ||
|
|
82cfda3dec | ||
|
|
bb998d1738 | ||
|
|
e9f23d51e0 | ||
|
|
34bb0c4943 | ||
|
|
e6a2bae5d7 | ||
|
|
f20a95fdc0 | ||
|
|
bda7310b46 | ||
|
|
dd60cb6645 | ||
|
|
53e735ffdd | ||
|
|
cc29f85862 | ||
|
|
cb72219b11 | ||
|
|
3dd3ecaff8 | ||
|
|
ca4862aabc | ||
|
|
9aabdba753 | ||
|
|
d3d97e7ef8 | ||
|
|
e25987df3a | ||
|
|
921f5c7680 | ||
|
|
2703a2b27c | ||
|
|
7800a7ef3f | ||
|
|
65efda425f | ||
|
|
b9d94e7bf0 | ||
|
|
49f9d185de | ||
|
|
ab9ff813fc | ||
|
|
ea690489d7 | ||
|
|
85b6f8dc2f | ||
|
|
b6b35d9482 | ||
|
|
e0a236a9af | ||
|
|
cd806b83db | ||
|
|
51f29cddb9 | ||
|
|
7807d6806c | ||
|
|
ad380e3ac6 | ||
|
|
debc6e4993 | ||
|
|
46ec26e745 | ||
|
|
2afe24f51c | ||
|
|
a75c672ee7 | ||
|
|
7215c1a3b1 | ||
|
|
2b8e24fb09 | ||
|
|
0e9c76abf8 | ||
|
|
f335f23145 | ||
|
|
8fec73673d | ||
|
|
fabfb66293 | ||
|
|
4ef3d99770 | ||
|
|
851d17f940 | ||
|
|
dcd19bba22 | ||
|
|
36296a3906 | ||
|
|
7f64474f3e | ||
|
|
2af7b3fd38 | ||
|
|
5d665b59a1 | ||
|
|
505bdb9c03 | ||
|
|
db53b8651c | ||
|
|
d49a968d55 | ||
|
|
1bcda5147a | ||
|
|
2b4c29e4f2 | ||
|
|
9f297c3140 | ||
|
|
41d9f612c7 | ||
|
|
ff8cc6f4c0 | ||
|
|
a3210e78aa | ||
|
|
e183cc62d9 | ||
|
|
77edb23291 | ||
|
|
6f13e9543b | ||
|
|
cba4e55ac4 | ||
|
|
41a650b699 | ||
|
|
e7dfa08756 | ||
|
|
0c4952447b | ||
|
|
3aee619fc0 | ||
|
|
3881e12a2d | ||
|
|
164269bff1 | ||
|
|
27b4f58b66 | ||
|
|
e8ad82c80f | ||
|
|
8bb4f53447 | ||
|
|
1e6508d2dc | ||
|
|
91ffd30f52 | ||
|
|
05c612f337 | ||
|
|
c1c046f2dd | ||
|
|
2abb459770 | ||
|
|
111bb52add | ||
|
|
190e63a6bb | ||
|
|
7b758493a3 | ||
|
|
2f83cf0dbd | ||
|
|
8231fb2c68 | ||
|
|
b263a00eac | ||
|
|
79a9ce5000 | ||
|
|
7ca0ac289e | ||
|
|
c98f9117c2 | ||
|
|
9445502885 | ||
|
|
6521e51170 | ||
|
|
e4935e58f2 | ||
|
|
15f76c62bb | ||
|
|
161ae31a7e | ||
|
|
b3e7493278 | ||
|
|
d8e165da8d | ||
|
|
79ff1f10d2 | ||
|
|
1635e0af4b | ||
|
|
1f2ce21b56 | ||
|
|
8e644e1303 | ||
|
|
958d35a3f3 | ||
|
|
04b23dbf10 | ||
|
|
47ac61b3e0 | ||
|
|
3398d1e287 | ||
|
|
2e79637be8 | ||
|
|
03d5922996 | ||
|
|
48aba0a3f0 | ||
|
|
6523f7f59e | ||
|
|
c1fd0c479a | ||
|
|
f55b5411c8 | ||
|
|
eb8f524f81 | ||
|
|
44c867827c | ||
|
|
bcddc47356 | ||
|
|
9ae5b8f442 | ||
|
|
548c997f7b | ||
|
|
0868ec1c19 | ||
|
|
a5b90fd3c6 | ||
|
|
dfae961913 | ||
|
|
70458b2f48 | ||
|
|
b32bb26a84 | ||
|
|
f54f8f8a95 | ||
|
|
738bfd8082 | ||
|
|
3e601c3a53 | ||
|
|
a9398e7a74 | ||
|
|
be6fb617df | ||
|
|
e2d15c3a04 | ||
|
|
f686a3ac1b | ||
|
|
e9f936c0ba | ||
|
|
d05ad996c4 | ||
|
|
f1571aeac3 | ||
|
|
93fcb74f9a | ||
|
|
1594831d8a | ||
|
|
3d8e46447a | ||
|
|
0af5da77f1 | ||
|
|
4ef552e07a | ||
|
|
a038f5edea | ||
|
|
758ffe06d2 | ||
|
|
e9974911fe | ||
|
|
67f0722211 | ||
|
|
790d98133c | ||
|
|
bd41e69a1f | ||
|
|
99e303e211 | ||
|
|
6103db0d04 | ||
|
|
f0db9a842d | ||
|
|
f566b79c87 | ||
|
|
63b2c03a02 | ||
|
|
e09a9c7deb | ||
|
|
37ce0f15d6 | ||
|
|
3403305b3d | ||
|
|
5fddd1bee5 | ||
|
|
3d852397db | ||
|
|
3ab6ad23ad | ||
|
|
0a09a28ec9 | ||
|
|
fa140d8f59 | ||
|
|
5c7d7c6f05 | ||
|
|
56fb1035de | ||
|
|
f63cb95ef3 | ||
|
|
85790f0752 | ||
|
|
4df3c75321 | ||
|
|
2f67750165 | ||
|
|
3085c52f95 | ||
|
|
9e010cbd34 | ||
|
|
30fdf8dd1b | ||
|
|
c827a98196 | ||
|
|
5392133beb | ||
|
|
3ddc461d30 | ||
|
|
29a94f4f52 | ||
|
|
a1ab3e8cf4 | ||
|
|
d5d47222c1 | ||
|
|
9b02745cd8 | ||
|
|
d95e96bd3b | ||
|
|
c008958950 | ||
|
|
59e598acc5 | ||
|
|
bad811df6a | ||
|
|
4b09712761 | ||
|
|
193ac077d6 | ||
|
|
c02ac6516e | ||
|
|
6cbdf53975 | ||
|
|
ad9d590a15 | ||
|
|
f8b1915efd | ||
|
|
52c49b444e | ||
|
|
9c87b5c689 | ||
|
|
4aa67a7598 | ||
|
|
b49180875c | ||
|
|
531eb68d56 | ||
|
|
6e93186db4 | ||
|
|
fdc9fdae3e | ||
|
|
8c407af1fc | ||
|
|
68665af6e8 | ||
|
|
0cc2583a02 | ||
|
|
f813223036 | ||
|
|
f018a56d6d | ||
|
|
3b79951824 | ||
|
|
015ea809b0 | ||
|
|
bfc7986b20 | ||
|
|
2b996128af | ||
|
|
91e4702772 | ||
|
|
530e4840dd | ||
|
|
aa381951cd | ||
|
|
cb7a77cc03 | ||
|
|
85ea27dba2 | ||
|
|
d1e868a32a | ||
|
|
37279d0753 | ||
|
|
c4a2eaea49 | ||
|
|
cbe4987e18 | ||
|
|
022d27e4e9 | ||
|
|
de26952e29 | ||
|
|
c92393026d | ||
|
|
d54fdf43d0 | ||
|
|
a1a9f85fda | ||
|
|
d6ccd82cf6 | ||
|
|
a5c13a5ef1 | ||
|
|
0b3577f2d2 | ||
|
|
49016bc156 | ||
|
|
efebf26cc5 | ||
|
|
84ec6dc9f5 | ||
|
|
1095fb39cb | ||
|
|
f7496b1482 | ||
|
|
d31c7f5e2b | ||
|
|
c32a77e6be | ||
|
|
fd2a22bd56 | ||
|
|
864fbbdaaf | ||
|
|
306f9e0ca2 | ||
|
|
3047c4b955 | ||
|
|
cc06508bd4 | ||
|
|
a2fd4eca37 | ||
|
|
029071a144 | ||
|
|
5005bbe62b | ||
|
|
e69b022472 | ||
|
|
4fc7389b1d | ||
|
|
5b18718b92 | ||
|
|
975f3c4600 | ||
|
|
c5c3719e79 | ||
|
|
04a4f2fc24 | ||
|
|
dd263ce00d | ||
|
|
f3a9b1efc0 | ||
|
|
290f8a79e4 | ||
|
|
7a5ae3a1a2 | ||
|
|
2811d161bb | ||
|
|
6d1209c06d | ||
|
|
67af9f1853 | ||
|
|
d6809773db | ||
|
|
449d8a66ad | ||
|
|
f591e428c3 | ||
|
|
0f9afbdf0a | ||
|
|
8a52e3033b | ||
|
|
df8626b949 | ||
|
|
ab15528fde | ||
|
|
08b455b029 | ||
|
|
16da74d1da | ||
|
|
c0620bf857 | ||
|
|
ffa372a76c | ||
|
|
505537d4ce | ||
|
|
68806aa8c6 | ||
|
|
aca1470e6b | ||
|
|
5a1c1e55ef | ||
|
|
43eebe1a8b | ||
|
|
19602d0a26 | ||
|
|
c4dcd39666 | ||
|
|
d09b733cc3 | ||
|
|
d4bcbd4741 | ||
|
|
74f52a055e | ||
|
|
155c24772a | ||
|
|
a3d8207578 | ||
|
|
beae0865db | ||
|
|
29318e183c | ||
|
|
18e63f9cea | ||
|
|
bc4cf21c9d | ||
|
|
7d7edbbd4a | ||
|
|
3aba23ea35 | ||
|
|
1b2b831feb | ||
|
|
7f3e90e291 | ||
|
|
6f3ef148a9 | ||
|
|
9cee329407 | ||
|
|
36dc560533 | ||
|
|
24e808844b | ||
|
|
44d7d23e8d | ||
|
|
a16ca32981 | ||
|
|
c3291f8f24 | ||
|
|
c65b22eadf | ||
|
|
2a399312f7 | ||
|
|
666ae8f1b7 | ||
|
|
e1704402a6 | ||
|
|
9c4e52c136 | ||
|
|
b346f1901a | ||
|
|
df82b6060b | ||
|
|
06eed4cfda | ||
|
|
de5e4b0fdc | ||
|
|
0e1eff14bc | ||
|
|
18f1d56b60 | ||
|
|
9b4d60897d | ||
|
|
c6ef7a7c03 | ||
|
|
cb892736eb | ||
|
|
694d0911c9 | ||
|
|
b2fa2cb195 | ||
|
|
84b31714a6 | ||
|
|
e46275e80d | ||
|
|
797c9cf70e | ||
|
|
df0632258a | ||
|
|
ce9643bce1 | ||
|
|
73db4e19d2 | ||
|
|
e3933e265e | ||
|
|
ac1ffaf7e9 | ||
|
|
775936399e | ||
|
|
23d004844a | ||
|
|
d57159ad54 | ||
|
|
33c5f4f678 | ||
|
|
0a835609fa | ||
|
|
3788d0e815 | ||
|
|
43f97a9abc | ||
|
|
53ff312936 | ||
|
|
7954386705 | ||
|
|
0a78f7bc11 | ||
|
|
4dd296f9ca | ||
|
|
3faa1a78c2 | ||
|
|
39ad87650e | ||
|
|
79d9c07652 | ||
|
|
47964a1605 | ||
|
|
ad871e8b26 | ||
|
|
c9d962b12a | ||
|
|
2f817b30c3 | ||
|
|
d2501a9e4a | ||
|
|
7798c94a40 | ||
|
|
edd5d14b06 | ||
|
|
f6a61b133e | ||
|
|
f1fe360788 | ||
|
|
e130df4f42 | ||
|
|
1a192b6530 | ||
|
|
6195d42778 | ||
|
|
794b4ef09c | ||
|
|
9cddaf3075 | ||
|
|
bf80ee6a30 | ||
|
|
a47e566382 | ||
|
|
1447884fde | ||
|
|
4a68b90f6f | ||
|
|
cb2c71b16a | ||
|
|
3d0e87bca9 | ||
|
|
48dcee9d60 | ||
|
|
78d3f647ff | ||
|
|
55a9e1e90c | ||
|
|
1bbd52b8ee | ||
|
|
9b9acd6e9e | ||
|
|
dbd646b2de | ||
|
|
502585bf40 | ||
|
|
af07bd7818 | ||
|
|
a32948b20f | ||
|
|
68436fee75 | ||
|
|
85d1707a2b | ||
|
|
35764c2402 | ||
|
|
5d352389b7 | ||
|
|
f040ed0cf0 | ||
|
|
6cd82d77f5 | ||
|
|
bd1bc07270 | ||
|
|
93f79d0810 | ||
|
|
9fc1d85e8d | ||
|
|
d995c6dbdc | ||
|
|
d1b2dabc0f | ||
|
|
e6b99c2059 | ||
|
|
2c3c5b34cf | ||
|
|
e5d1f9e724 | ||
|
|
1d927541e2 | ||
|
|
3419c65efe | ||
|
|
2e81fbfd64 | ||
|
|
da9b2e805e | ||
|
|
cdde6e8a5c | ||
|
|
5d01123413 | ||
|
|
38d725ce32 | ||
|
|
86054eb659 | ||
|
|
600d0ba2a2 | ||
|
|
299def4712 | ||
|
|
19a4d05035 | ||
|
|
bea78f42e3 | ||
|
|
e774b1d8c0 | ||
|
|
3c4d2cd890 | ||
|
|
120bad8a2c | ||
|
|
6b1ef08a46 | ||
|
|
359a9c015b | ||
|
|
2ce705ceb3 | ||
|
|
16b22f0f31 | ||
|
|
585ba534a6 | ||
|
|
3407620bf8 | ||
|
|
f9e943fefb | ||
|
|
551df4af52 | ||
|
|
fac820f0e2 | ||
|
|
88bbee127c | ||
|
|
d68fcd8bd2 | ||
|
|
35fc3c0671 | ||
|
|
7dae89bb02 | ||
|
|
f0a09a2d52 | ||
|
|
8027fca378 | ||
|
|
d9bb861b1f | ||
|
|
1d2f46bda7 | ||
|
|
aca20fc615 | ||
|
|
c6c82efe07 | ||
|
|
5dc0081f56 | ||
|
|
8bf1c96ae1 | ||
|
|
775071e1ff | ||
|
|
358bb2ec33 | ||
|
|
9f831f4c98 | ||
|
|
0fce3c8f97 | ||
|
|
1d46d2b9af | ||
|
|
faf92883b6 | ||
|
|
44831f21c1 | ||
|
|
6c24251452 | ||
|
|
1d6a21f7fa | ||
|
|
0f3abde413 | ||
|
|
febfe35c23 | ||
|
|
74f3ed7e29 | ||
|
|
b98280a504 | ||
|
|
e0fc09994c | ||
|
|
d39760ba49 | ||
|
|
543c73bc05 | ||
|
|
c1012f7970 | ||
|
|
2bb511584e | ||
|
|
0f07044836 | ||
|
|
fdb2b9c655 | ||
|
|
21c9be74c9 | ||
|
|
28403abe78 | ||
|
|
a029b28423 | ||
|
|
56c49fedd2 | ||
|
|
a12e5ac8a7 | ||
|
|
27451a59d4 | ||
|
|
47e56de443 | ||
|
|
56ea4872ca | ||
|
|
36ce26691d | ||
|
|
5deebc8738 | ||
|
|
3c391f8f37 | ||
|
|
cd6b584722 | ||
|
|
e8e830f10a | ||
|
|
9950af2f58 | ||
|
|
106f10513f | ||
|
|
6ffe4d3dda | ||
|
|
ea14bcff4a | ||
|
|
f76d327413 | ||
|
|
72d5d0281a | ||
|
|
69f0d70a98 | ||
|
|
bab14bfd24 | ||
|
|
f26d43b3ea | ||
|
|
52ee848bcb | ||
|
|
bb10211983 | ||
|
|
da7fd2ece7 | ||
|
|
e7a6d87990 | ||
|
|
c1dae35a24 | ||
|
|
615e22073f | ||
|
|
adec530c13 | ||
|
|
41ae873048 | ||
|
|
d0b0b0ce59 | ||
|
|
773fbd9edb | ||
|
|
0014afe746 | ||
|
|
e16803de61 | ||
|
|
53ecedf70a | ||
|
|
b09201ae88 | ||
|
|
59e9d55077 | ||
|
|
facd64ef2f | ||
|
|
d34c39555d | ||
|
|
8d3d604ed3 | ||
|
|
4deeb23af0 | ||
|
|
781a661704 | ||
|
|
d8227fcd06 | ||
|
|
3fff83cd13 | ||
|
|
133232eb6b | ||
|
|
ef8703e3e9 | ||
|
|
a07fc515c7 | ||
|
|
76e4f5a80b | ||
|
|
c7d8c9f34e | ||
|
|
1cecc9c429 | ||
|
|
ea2d4e4282 | ||
|
|
80408ac34f | ||
|
|
9bdf9a9904 | ||
|
|
9a0d36ae86 | ||
|
|
c6730de3d1 | ||
|
|
239ffe468a | ||
|
|
b558ffd694 | ||
|
|
9f3967d65d | ||
|
|
4ae7851a04 | ||
|
|
12c3a42d8c | ||
|
|
e43897916a | ||
|
|
ab4482b617 | ||
|
|
ae4321b4e3 | ||
|
|
bf8924df14 | ||
|
|
4cc61bf2ee | ||
|
|
82bea24426 | ||
|
|
87e0c69381 | ||
|
|
a6deb51a05 | ||
|
|
959a68694e | ||
|
|
9d398afa56 | ||
|
|
21cfe4ba9f | ||
|
|
e5cf1da4ee | ||
|
|
bd49aa5d2c | ||
|
|
3cbb3eab18 | ||
|
|
ff4ed93707 | ||
|
|
abb258c951 | ||
|
|
603f7a1664 | ||
|
|
e3acf43dbc | ||
|
|
1eddb53d6c | ||
|
|
93df588d87 | ||
|
|
9b1092726d | ||
|
|
223577d8b5 | ||
|
|
8bdb713073 | ||
|
|
6d5f15e708 | ||
|
|
eac34b6d6a | ||
|
|
da0a6fc619 | ||
|
|
83a9458653 | ||
|
|
8b1f60c9f8 | ||
|
|
537821418e | ||
|
|
8368f0e4b9 | ||
|
|
4cf5f70bea | ||
|
|
c3c174512a | ||
|
|
f49a4e9c40 | ||
|
|
223c47069e | ||
|
|
a038e6cbad | ||
|
|
ec58285b3f | ||
|
|
909dbdf29d | ||
|
|
c2cee0d6eb | ||
|
|
177adbdfc7 | ||
|
|
62be27b295 | ||
|
|
06de4e62a5 | ||
|
|
b91689fe2f | ||
|
|
f6f2acad4c | ||
|
|
ca470d8ba7 | ||
|
|
0551ccca92 | ||
|
|
6136654dad | ||
|
|
9d906fa31e | ||
|
|
dcaf1b5891 | ||
|
|
9f81d5d077 | ||
|
|
d3e697143f | ||
|
|
e90545cef5 | ||
|
|
0a01b14830 | ||
|
|
4bc014c696 | ||
|
|
e45ebbac46 | ||
|
|
24dc74a800 | ||
|
|
772f58a95b | ||
|
|
f6eb83705a | ||
|
|
4879c50c5d | ||
|
|
6c4aaab2d6 | ||
|
|
cd6131c9b8 | ||
|
|
f2d8102bbf | ||
|
|
86f67788c5 | ||
|
|
ea5108ea0f | ||
|
|
5c89d7ffcb | ||
|
|
568698e321 | ||
|
|
b545525e13 | ||
|
|
bf32125bad | ||
|
|
a9035e1533 | ||
|
|
68663fac4b | ||
|
|
b1b10042d2 | ||
|
|
bf9024b622 | ||
|
|
108cb53eef | ||
|
|
e035fe7949 | ||
|
|
40800bd3cd | ||
|
|
4f67ea3869 | ||
|
|
8c6c49a6ee | ||
|
|
7f8f39168a | ||
|
|
bd07f8d3dd | ||
|
|
a8478d5766 | ||
|
|
f6d9344d89 | ||
|
|
91e700a70e | ||
|
|
de769c6c3c | ||
|
|
29fabbd81f | ||
|
|
5160bdc1a8 | ||
|
|
003d1410b0 | ||
|
|
9b877499c7 | ||
|
|
9cd8f85a8c | ||
|
|
072094f722 | ||
|
|
170271fd72 | ||
|
|
bb47e90696 | ||
|
|
20c859611a | ||
|
|
36a47e391c | ||
|
|
267ce7df88 | ||
|
|
cfe1259400 | ||
|
|
6015253064 | ||
|
|
98bd5cae64 | ||
|
|
d7042ab828 | ||
|
|
cac9928f28 | ||
|
|
289c186de5 | ||
|
|
cd04cbc7c4 | ||
|
|
5b5fb2b732 | ||
|
|
e8a47b3921 | ||
|
|
017a7d889f | ||
|
|
41a3d90a57 | ||
|
|
99e46a23c6 | ||
|
|
65c2b498ad | ||
|
|
f7ede572e0 | ||
|
|
43ef8765fd | ||
|
|
bda98150c4 | ||
|
|
ef12a09ae0 | ||
|
|
2fdb55a878 | ||
|
|
b6d776f75d | ||
|
|
ad6130b02d | ||
|
|
ca5dbb182a | ||
|
|
69b1eb5c64 | ||
|
|
0f501114eb | ||
|
|
f7175c229e | ||
|
|
853a0ee865 | ||
|
|
40d094fea2 | ||
|
|
f6d2b00d5c | ||
|
|
57970499fd | ||
|
|
bd0fb574e3 | ||
|
|
2ce9246733 | ||
|
|
954b5077e4 | ||
|
|
0febf06114 | ||
|
|
33c5b639b0 | ||
|
|
8e50a31b98 | ||
|
|
c6a89c64f3 | ||
|
|
df19e68a86 | ||
|
|
5e91f0c1ca | ||
|
|
efe7a01482 | ||
|
|
f4663f4512 | ||
|
|
e8d30068e2 | ||
|
|
04635ad4ff | ||
|
|
eaec259186 | ||
|
|
3b7d16c60f | ||
|
|
33c68df3ba | ||
|
|
4c842974b4 | ||
|
|
752b502326 | ||
|
|
e98c775f0d | ||
|
|
0380d5ae58 | ||
|
|
a26990c3e8 | ||
|
|
2f6b930a8d | ||
|
|
2642daa438 | ||
|
|
619a31913a | ||
|
|
5e3e8b3957 | ||
|
|
bf1cc29a2a | ||
|
|
f6d5f0481e | ||
|
|
4c94a7ccc5 | ||
|
|
5b73f1bd82 | ||
|
|
353ba4dfd1 | ||
|
|
f13f44a2fc | ||
|
|
356f5874bf | ||
|
|
24f6b74427 | ||
|
|
c92b78bc06 | ||
|
|
b72d150d33 | ||
|
|
a8787be0bf | ||
|
|
9d1402e4a5 | ||
|
|
84086915e4 | ||
|
|
0a4fbc9770 | ||
|
|
2b97f79bd3 | ||
|
|
6bcfaed640 | ||
|
|
e2953c8cd4 | ||
|
|
48b6356e53 | ||
|
|
955497e3d5 | ||
|
|
82daf651fb | ||
|
|
cd0915deb5 | ||
|
|
ffc722a334 | ||
|
|
3f942e05f3 | ||
|
|
62ec98a9fc | ||
|
|
f2467dd30e | ||
|
|
0c12d3ed5a | ||
|
|
f2f32ca70f | ||
|
|
b8ac2fb416 | ||
|
|
10e74040af | ||
|
|
2b7360e738 | ||
|
|
be48821e86 | ||
|
|
68027e1b5f | ||
|
|
ef33454301 | ||
|
|
bfcea9460b | ||
|
|
b80ef58cab | ||
|
|
be4eb63c62 | ||
|
|
16aa558292 | ||
|
|
135e515e7f | ||
|
|
7ca43b72c9 | ||
|
|
248c9bdeff | ||
|
|
4042bc53ce | ||
|
|
841d12e9b6 | ||
|
|
507c8f45b4 | ||
|
|
bda593a66d | ||
|
|
8eaf160ead | ||
|
|
53b3030aa2 | ||
|
|
dc0a03ab30 | ||
|
|
6f35679911 | ||
|
|
f9a4dcb2d0 | ||
|
|
a0d6d84a4f | ||
|
|
166c05dfaa | ||
|
|
ab4d3c3a09 | ||
|
|
9e8a950f2e | ||
|
|
0d4e0626cf | ||
|
|
ef0a901cf5 | ||
|
|
ceadc95439 | ||
|
|
61e371cbdc | ||
|
|
b44ff9b849 | ||
|
|
2187f33477 | ||
|
|
24432bd0ab | ||
|
|
82a1626e82 | ||
|
|
f4da4591fa | ||
|
|
43b1e79ec4 | ||
|
|
aeb2ab132b | ||
|
|
4cbd5eac95 | ||
|
|
2d14be86f3 | ||
|
|
08edf34057 | ||
|
|
9916f34262 | ||
|
|
a0ee72f264 | ||
|
|
3f8347a4d9 | ||
|
|
14f20c16bc | ||
|
|
3dd5d14977 | ||
|
|
77e076f1fd | ||
|
|
45d95ad130 | ||
|
|
9b32a2d87a | ||
|
|
3e95eed76e | ||
|
|
34c94dbd94 | ||
|
|
98033cc878 | ||
|
|
909504c074 | ||
|
|
4c7e4296c9 | ||
|
|
1b7eacd9fa | ||
|
|
8af0f9d071 | ||
|
|
0632b37492 | ||
|
|
81cc6d9da8 | ||
|
|
e8eda4aeae | ||
|
|
c648981f28 | ||
|
|
c87d5af243 | ||
|
|
077d4a0e15 | ||
|
|
0fdffb9dbc | ||
|
|
c2bb281e80 | ||
|
|
6b0cd7b604 | ||
|
|
bb853722dc | ||
|
|
4571e498b4 | ||
|
|
4e10a95dca | ||
|
|
e9068a1552 | ||
|
|
64b649ef61 | ||
|
|
70f0136c8a | ||
|
|
6520211df3 | ||
|
|
056b34d847 | ||
|
|
f7c46c7b33 | ||
|
|
146f8f81f7 | ||
|
|
5aeabcb445 | ||
|
|
01697fee3d | ||
|
|
450d92872a | ||
|
|
a14ba1e561 | ||
|
|
4d425317b4 | ||
|
|
1f55351f19 | ||
|
|
9c9f85ed4b | ||
|
|
3131103801 | ||
|
|
d9ec0a59ec | ||
|
|
2ddfc6af5a | ||
|
|
c391287cc4 | ||
|
|
d943e67c65 | ||
|
|
39ed719c4c | ||
|
|
3914e4a5d0 | ||
|
|
cce3798b4b | ||
|
|
e99b800406 | ||
|
|
0cc176aae2 | ||
|
|
6707129a3e | ||
|
|
32b8d77580 | ||
|
|
96aa25fb3e | ||
|
|
ea69d9ca0c | ||
|
|
c6a3ff4da5 | ||
|
|
9c4c06c422 | ||
|
|
793a1032e6 | ||
|
|
ca438fa110 | ||
|
|
305da5b8ff | ||
|
|
3c31d88810 | ||
|
|
058242fa27 | ||
|
|
d1bfd57fd9 | ||
|
|
53055f1fb2 | ||
|
|
9ccce8ed74 | ||
|
|
d532de9da3 | ||
|
|
afb8d63fcb | ||
|
|
98e3e04477 | ||
|
|
4b316ec54f | ||
|
|
c965d231b1 | ||
|
|
abb129028a | ||
|
|
e31e164896 | ||
|
|
c38d273c1f | ||
|
|
88bda9b0d5 | ||
|
|
53386e5247 | ||
|
|
231d84b625 | ||
|
|
22b3b46b61 | ||
|
|
0f938b8c1d | ||
|
|
3994b80aa4 | ||
|
|
54217bd4c6 | ||
|
|
1dc5b7fba4 | ||
|
|
3b819b52ca | ||
|
|
95193ab5f8 | ||
|
|
11f82bd41f | ||
|
|
d444f0e06b | ||
|
|
c246c6b28b | ||
|
|
3cfa479c01 | ||
|
|
67497ed834 | ||
|
|
64d405f7dd | ||
|
|
94c288a6a8 | ||
|
|
2c036b3185 | ||
|
|
1bbec8dd33 | ||
|
|
30731e0727 | ||
|
|
50e028212d | ||
|
|
fb55e8094b | ||
|
|
96cb3d8004 | ||
|
|
e39bfced4a | ||
|
|
15562d030e | ||
|
|
0ec2cc557f | ||
|
|
7d921a8220 | ||
|
|
f232e45efe | ||
|
|
7be98f475e | ||
|
|
66d2b9e0fb | ||
|
|
3745e948c6 | ||
|
|
1f06e9fca5 | ||
|
|
7841ccb7c0 | ||
|
|
1579c43433 | ||
|
|
fbfd59afa0 | ||
|
|
f34eb83a7c | ||
|
|
8db1a09001 | ||
|
|
4a0227e5f2 | ||
|
|
a98c7df2f1 | ||
|
|
5918058d86 | ||
|
|
c5ef21864f | ||
|
|
d09285e9d3 | ||
|
|
035ca8e500 | ||
|
|
0a5a23628f | ||
|
|
cfe7ab46f2 | ||
|
|
3b9312e291 | ||
|
|
5b64dbe195 | ||
|
|
48bf5022e4 | ||
|
|
99c1383ef5 | ||
|
|
a02b0c9269 | ||
|
|
0cdf1e042c | ||
|
|
1873302ee9 | ||
|
|
7efd615b8c | ||
|
|
cdb452b27b | ||
|
|
f5330741ac | ||
|
|
5f80b57554 | ||
|
|
cb76222e63 | ||
|
|
1b83fcc46d | ||
|
|
a8052dec37 | ||
|
|
adc4840cce | ||
|
|
993d6f5ac8 | ||
|
|
80c9690926 | ||
|
|
d9740e2028 | ||
|
|
f1df4ffca4 | ||
|
|
91d8829c43 | ||
|
|
20ed8869e4 | ||
|
|
66e2a9260e | ||
|
|
9b8d2d512b | ||
|
|
fd00f2d371 | ||
|
|
5d3298e706 | ||
|
|
fa8000fa5c | ||
|
|
5e28273548 | ||
|
|
46a3fecb4f | ||
|
|
079e2b1302 | ||
|
|
b910a487c5 | ||
|
|
f569a2a389 | ||
|
|
719e05e53e | ||
|
|
a8906ce572 | ||
|
|
5392737de4 | ||
|
|
3aea203b9c | ||
|
|
dba8360166 | ||
|
|
23560038b4 | ||
|
|
d4059b88ca | ||
|
|
baef4f735f | ||
|
|
01f1924a89 | ||
|
|
07ce4092cd | ||
|
|
4a50eb4fa7 | ||
|
|
fe84a61d0b | ||
|
|
fde9d122cc | ||
|
|
92acd32410 | ||
|
|
596ba3d5b1 | ||
|
|
ca01065c6a | ||
|
|
be3adfb35e | ||
|
|
8f092812c4 | ||
|
|
9c1202a766 | ||
|
|
e19fd756cb | ||
|
|
7345c795ac | ||
|
|
753f75cfb9 | ||
|
|
97321a1ff2 | ||
|
|
0d57ffbc3b | ||
|
|
c3ec6e383c | ||
|
|
0b1f6e3539 | ||
|
|
b8af241504 | ||
|
|
91bc9c0329 | ||
|
|
fea855004c | ||
|
|
83a8ed01e7 | ||
|
|
2b663ff2bc | ||
|
|
1a602a8cb3 | ||
|
|
939fbf9c24 | ||
|
|
22a04fd6de | ||
|
|
8466060797 | ||
|
|
ba5e73213b | ||
|
|
a8e6131e3b | ||
|
|
ee924ffaba | ||
|
|
2730f64d90 | ||
|
|
cb0e5dbff3 | ||
|
|
fc738455b6 | ||
|
|
0252d55c67 | ||
|
|
eeba947ea7 | ||
|
|
33bcf7ad6f | ||
|
|
58b381bf24 | ||
|
|
4474d305cb | ||
|
|
7c244abc1c | ||
|
|
5c78ecaca1 | ||
|
|
7b71b3284d | ||
|
|
7e571212a7 | ||
|
|
75e1d17d18 | ||
|
|
a82bffbfc9 | ||
|
|
ba38f3e1e9 | ||
|
|
46541755ca | ||
|
|
18fd29613c | ||
|
|
1f59001ff7 | ||
|
|
3dc30dee11 | ||
|
|
cab154b873 | ||
|
|
7f5844c209 | ||
|
|
c5e51e6fa9 | ||
|
|
fdb9fb1c2b | ||
|
|
b6c49863e8 | ||
|
|
d0383f93d0 | ||
|
|
08716d9f72 | ||
|
|
73101be422 | ||
|
|
6f3667201c | ||
|
|
d46352da01 | ||
|
|
30149e48f9 | ||
|
|
52cea01563 | ||
|
|
f54cdf625e | ||
|
|
cb21f3c5ff | ||
|
|
cb28bfd484 | ||
|
|
8d1b852aa2 | ||
|
|
f47e1feac6 | ||
|
|
84dbb08502 | ||
|
|
e38076c19a | ||
|
|
3b46df68ea | ||
|
|
dd6f6cb097 | ||
|
|
640facd26a | ||
|
|
291d2fd624 | ||
|
|
9ece0fe3c9 | ||
|
|
3801e0c230 | ||
|
|
2166a21511 | ||
|
|
894bbb020c | ||
|
|
772b413579 | ||
|
|
2518f0687c | ||
|
|
f86e1ba66c | ||
|
|
097d573d26 | ||
|
|
4a920d0aad | ||
|
|
6a72ba5f97 | ||
|
|
92b16455c8 | ||
|
|
a36a1624fb | ||
|
|
97a6caf059 | ||
|
|
509e5fb12f | ||
|
|
c7c875a063 | ||
|
|
45308d5f79 | ||
|
|
9058bc3f5c | ||
|
|
89470787d8 | ||
|
|
de98f3fb30 | ||
|
|
15877e1443 | ||
|
|
1681d8a893 | ||
|
|
f3b6ed03f3 | ||
|
|
689aaef4dc | ||
|
|
bf44be86a9 | ||
|
|
24042863ac | ||
|
|
ebe933810e | ||
|
|
8efae0b232 | ||
|
|
cd28051370 | ||
|
|
d24f288149 | ||
|
|
b28af2e527 | ||
|
|
80284a273d | ||
|
|
d2cd6560c5 | ||
|
|
919f5e5ebc | ||
|
|
9f96d4a31a | ||
|
|
5fe996baf9 | ||
|
|
43c25ea36d | ||
|
|
cd7029d266 | ||
|
|
c02920762b | ||
|
|
728724bed5 | ||
|
|
e94b902a9b | ||
|
|
f4c5c4ba01 | ||
|
|
9795cb1f0d | ||
|
|
a86038b484 | ||
|
|
01d900d5d7 | ||
|
|
944f802d79 | ||
|
|
2b334977f5 | ||
|
|
90725fa529 | ||
|
|
2ae3bb6e3a | ||
|
|
1fb213760b | ||
|
|
63a3fb5ad8 | ||
|
|
00321e8f70 | ||
|
|
918e2d2018 | ||
|
|
3bb803fd69 | ||
|
|
f8811c4d21 | ||
|
|
3707b34cbb | ||
|
|
43ccd9ead6 | ||
|
|
ee80ec4851 | ||
|
|
84cd22d7f7 | ||
|
|
7ebfc67d5a | ||
|
|
19d0887bb0 | ||
|
|
7f0275155d | ||
|
|
6a89de51e5 | ||
|
|
54a53b1d03 | ||
|
|
f6d34bbb9d | ||
|
|
2b3bee1fa4 | ||
|
|
01c9a4ac1c | ||
|
|
a7f3af8328 | ||
|
|
b2d98495b1 | ||
|
|
25ecd45fd1 | ||
|
|
82f7d6cad2 | ||
|
|
bd5393a318 | ||
|
|
e3d133af04 | ||
|
|
6ec2ae249b | ||
|
|
2cfc61db84 | ||
|
|
c30e129390 | ||
|
|
b333ff95fb | ||
|
|
6bbf2d9da3 | ||
|
|
ddfdb37a58 | ||
|
|
666691f84f | ||
|
|
b6a7520c64 | ||
|
|
09ac3a9eb2 | ||
|
|
342c3ba941 | ||
|
|
88574a0de2 | ||
|
|
f6f6edbd59 | ||
|
|
f29c907f41 | ||
|
|
3b3186ee98 | ||
|
|
ecc556f687 | ||
|
|
53a153bc15 | ||
|
|
800628e3cd | ||
|
|
8b38e68e23 | ||
|
|
7ba656f815 | ||
|
|
240f0ea34c | ||
|
|
12f46e936c | ||
|
|
e7f471ef3e | ||
|
|
0a6709acba | ||
|
|
c948ad852e | ||
|
|
b145f061c9 | ||
|
|
e6a73803a4 | ||
|
|
3b4b38e184 | ||
|
|
7da9beed36 | ||
|
|
3bee695913 | ||
|
|
d3b27dcb1a | ||
|
|
4f22bbbc76 | ||
|
|
2e389e00d4 | ||
|
|
5fc6277d3f | ||
|
|
d314386060 | ||
|
|
e69e0fcc71 | ||
|
|
b560551b1d | ||
|
|
b83945d486 | ||
|
|
3c82b49cd3 | ||
|
|
8c2db89f2b | ||
|
|
06d56156dd | ||
|
|
736443f6c2 | ||
|
|
d7fbd2cd14 | ||
|
|
ed0fb4ece7 | ||
|
|
7433148f17 | ||
|
|
3800581947 | ||
|
|
2653d735e2 | ||
|
|
3b1ddb0346 | ||
|
|
6857134f36 | ||
|
|
f148912a28 | ||
|
|
b9a24b5487 | ||
|
|
2ee3cdeb0c | ||
|
|
7782780cda | ||
|
|
6e47d7b16d | ||
|
|
a0ca506db7 | ||
|
|
63a2f02f4d | ||
|
|
a04d2933fa | ||
|
|
25f5ff0ca1 | ||
|
|
745535d269 | ||
|
|
05fb0b913a | ||
|
|
e13720c33d | ||
|
|
07e1c1e2e1 | ||
|
|
816ce41f63 | ||
|
|
1666d59da4 | ||
|
|
bcc7bb1c9c | ||
|
|
15c877b8e8 | ||
|
|
19682bf87a | ||
|
|
7e47a601b0 | ||
|
|
c85de03b66 | ||
|
|
d3beb7e23e | ||
|
|
ba882be76b | ||
|
|
e12a5fb328 | ||
|
|
d583b149ac | ||
|
|
4675f65bea | ||
|
|
816039f23f | ||
|
|
953a0f6572 | ||
|
|
c34612b8e9 | ||
|
|
f8558d7740 | ||
|
|
5c47c07794 | ||
|
|
3d788a10cf | ||
|
|
8f589e5876 | ||
|
|
1250cd7a5a | ||
|
|
d439f67df5 | ||
|
|
d7dbde8f3e | ||
|
|
b2951691e2 | ||
|
|
656beb635c | ||
|
|
196632978c | ||
|
|
d1e9bc6401 | ||
|
|
a47af43bc1 | ||
|
|
7f20a32db3 | ||
|
|
154fd60d85 | ||
|
|
a0b7c3e76d | ||
|
|
7584ef6ba1 | ||
|
|
57cfcfd20e | ||
|
|
e73605e177 | ||
|
|
6abe8e412c | ||
|
|
79d99b11ad | ||
|
|
41a9e9689b | ||
|
|
598ab36968 | ||
|
|
2e3d2398d9 | ||
|
|
93d2e1bd0a | ||
|
|
cbf210605a | ||
|
|
2a59da1f03 | ||
|
|
a99ffc126f | ||
|
|
423651e45e | ||
|
|
6cf7bdc2b7 | ||
|
|
1d9016e48f | ||
|
|
97a4dbf2cd | ||
|
|
7261060905 | ||
|
|
1ea3e543ab | ||
|
|
49c735109c | ||
|
|
6ef4ac62d7 | ||
|
|
b58f573b31 | ||
|
|
65f7e897b5 | ||
|
|
e3dcfa8702 | ||
|
|
4b85d7a683 | ||
|
|
6163d9d932 | ||
|
|
afd7a540a7 | ||
|
|
4266ab77b2 | ||
|
|
4cf63a4e83 | ||
|
|
d1908f7207 | ||
|
|
277fc751b6 | ||
|
|
b867744f15 | ||
|
|
a85902b08d | ||
|
|
4be7c3dac0 | ||
|
|
01d6ec35c4 | ||
|
|
570799b48d | ||
|
|
0e6121e8f5 | ||
|
|
99bdf65c10 | ||
|
|
180dbbad8b | ||
|
|
d9b1dbbb09 | ||
|
|
c87dedbec5 | ||
|
|
4796452b07 | ||
|
|
fb11268255 | ||
|
|
98fabd98be | ||
|
|
5733574867 | ||
|
|
409c16b898 | ||
|
|
c261315ea7 | ||
|
|
8b92dc5265 | ||
|
|
442a2b3a51 | ||
|
|
305e0345ef | ||
|
|
a8048af65d | ||
|
|
d7da292f60 | ||
|
|
689eaf3172 | ||
|
|
2b207106a3 | ||
|
|
9d1a647753 | ||
|
|
b6bd46dbed | ||
|
|
9a68074878 | ||
|
|
ac76dafe62 | ||
|
|
ef663c83f3 | ||
|
|
024b7b7cb6 | ||
|
|
dfdb735306 | ||
|
|
cb49648eed | ||
|
|
5c2a4c0339 | ||
|
|
2858b8290f | ||
|
|
a638154046 | ||
|
|
a947e8a4b0 | ||
|
|
8e7c156451 | ||
|
|
0529efc843 | ||
|
|
438dd9141f | ||
|
|
db37d974c8 | ||
|
|
6b54cceed7 | ||
|
|
73f908f25c | ||
|
|
550fcbc17f | ||
|
|
ffca455788 | ||
|
|
e4f2a56277 | ||
|
|
cbe14a694a | ||
|
|
f589cd0d9f | ||
|
|
43d8466fa9 | ||
|
|
5299bd788f | ||
|
|
a0a81db045 | ||
|
|
5362206297 | ||
|
|
e32e141012 | ||
|
|
4603e94fe9 | ||
|
|
8b7e2a9f32 | ||
|
|
5701036068 | ||
|
|
0f68355ce0 | ||
|
|
9395eeed3d | ||
|
|
6d035be3e3 | ||
|
|
01935e6661 | ||
|
|
379584fb26 | ||
|
|
f1c073e080 | ||
|
|
66e92b147d | ||
|
|
c19d7fe2eb | ||
|
|
9ae30421dd | ||
|
|
53c799987d | ||
|
|
8850efb0eb | ||
|
|
551f6d05d9 | ||
|
|
e899205300 | ||
|
|
5afc097527 | ||
|
|
ed516edf90 | ||
|
|
52431251cb | ||
|
|
69944017d2 | ||
|
|
ca0bea1d8a | ||
|
|
7efe071ac4 | ||
|
|
ebe95af30c | ||
|
|
a607e2ec7a | ||
|
|
a73a1e8437 | ||
|
|
07f568e2b4 | ||
|
|
0dd1dc20c8 | ||
|
|
7367e255ae | ||
|
|
10b70df1af | ||
|
|
fe8b28a09f | ||
|
|
db80b2b135 | ||
|
|
a5cddb0c11 | ||
|
|
3717ae3c53 | ||
|
|
2caf0fff60 | ||
|
|
c05fffcc93 | ||
|
|
fff0204e6d | ||
|
|
c7c430032c | ||
|
|
1c2ade61ab | ||
|
|
c62e27898c | ||
|
|
6f8ac21273 | ||
|
|
82f0c244e8 | ||
|
|
197744a57f | ||
|
|
054ac220ac | ||
|
|
c6746d4a4a | ||
|
|
f0bc3d925d | ||
|
|
7810f5fe69 | ||
|
|
decd1482de | ||
|
|
fa7574b2ba | ||
|
|
32b146ea8a | ||
|
|
1aa90dc872 | ||
|
|
989d375be5 | ||
|
|
ede68ec87b | ||
|
|
02f06b6d52 | ||
|
|
699ccfddb6 | ||
|
|
626e467a17 | ||
|
|
1fed340793 | ||
|
|
0cd0ae49a1 | ||
|
|
713f4654fd | ||
|
|
22bdb1520a | ||
|
|
42c5382a03 | ||
|
|
98bc3c4e40 | ||
|
|
d1106a730b | ||
|
|
da2d83fc7d | ||
|
|
ec748b2a16 | ||
|
|
5ff44b5ec7 | ||
|
|
dd329c903d | ||
|
|
3be6218341 | ||
|
|
71082bdba8 | ||
|
|
866534334f | ||
|
|
b37c8f6a23 | ||
|
|
df500033bf | ||
|
|
05bf8477a3 | ||
|
|
2b52eff4eb | ||
|
|
d5daf161c6 | ||
|
|
12dfb5ee38 | ||
|
|
39ee9e5e5b | ||
|
|
c7eaf77d15 | ||
|
|
524c799e37 | ||
|
|
fe527fbf1a | ||
|
|
037daff891 | ||
|
|
9945296472 | ||
|
|
fdbc909bde | ||
|
|
1f6b49d236 | ||
|
|
3cdb4e007d | ||
|
|
a4cbb23fc8 | ||
|
|
97573425f9 | ||
|
|
4371e8fab0 | ||
|
|
22826ac10d | ||
|
|
543432bf53 | ||
|
|
d17d0f5452 | ||
|
|
d3ab9b51fa | ||
|
|
ddb647f39f | ||
|
|
70d756d59c | ||
|
|
f3677554e8 | ||
|
|
3cdff65761 | ||
|
|
ff30f86082 | ||
|
|
1038a866a4 | ||
|
|
2c9a12771b | ||
|
|
bda4165bf8 | ||
|
|
84aefd6340 | ||
|
|
acaf08d4b7 | ||
|
|
875912bffd | ||
|
|
86c3744b8c | ||
|
|
875f5c1fa8 | ||
|
|
6468740915 | ||
|
|
79643e32ed | ||
|
|
bf0775fbb6 | ||
|
|
7ee8dc4e44 | ||
|
|
23540c17f1 | ||
|
|
bb873826ca | ||
|
|
93521217a6 | ||
|
|
693fc090b5 | ||
|
|
ca6ea65b1f | ||
|
|
3adbf0de39 | ||
|
|
a0d79b03e7 | ||
|
|
2b3d0a209c | ||
|
|
6d724ad9ff | ||
|
|
0bb0937372 | ||
|
|
bc4e14a99f | ||
|
|
cec62db2d8 | ||
|
|
262ae7c942 | ||
|
|
85fb1a3ebb | ||
|
|
a979852ee6 | ||
|
|
9ea03de84f | ||
|
|
9f01e9563f | ||
|
|
f4021e7469 | ||
|
|
5d81e867be | ||
|
|
85d40847ac | ||
|
|
5e938b3147 | ||
|
|
2cfdf2b05d | ||
|
|
d45f7c1302 | ||
|
|
34ad2ccbf1 | ||
|
|
83372bd144 | ||
|
|
1b4f0a5e1f | ||
|
|
14d630ae1c | ||
|
|
cb3615ab47 | ||
|
|
e66970b78b | ||
|
|
2a7364bb18 | ||
|
|
f4d62b317e | ||
|
|
551247d11a | ||
|
|
08f2af489e | ||
|
|
e538128645 | ||
|
|
1e9e2de737 | ||
|
|
8e3fdc5adc | ||
|
|
814473c27d | ||
|
|
a45a02fd64 | ||
|
|
905e05cd36 | ||
|
|
75b69f946d | ||
|
|
a112be79ef | ||
|
|
54a0109d5d | ||
|
|
0d0d61935f | ||
|
|
b959ab37bf | ||
|
|
b025b2b343 | ||
|
|
bffca232e2 | ||
|
|
19dfe7b891 | ||
|
|
ce1e446227 | ||
|
|
5d1905de13 | ||
|
|
23131d6860 | ||
|
|
d4569baa11 | ||
|
|
b5520aa304 | ||
|
|
c53baa9935 | ||
|
|
d0b95bb31c | ||
|
|
7a068c206e | ||
|
|
5a6ac2fb56 | ||
|
|
6b3dfaccfc | ||
|
|
e3d2a0e293 | ||
|
|
a141aaf663 | ||
|
|
85d6b9fd39 | ||
|
|
e9067eb4a3 | ||
|
|
0c955fe54f | ||
|
|
ea5a623c88 | ||
|
|
73c7605a5c | ||
|
|
0b1077a3b3 | ||
|
|
5179ff921b | ||
|
|
abbb3e8656 | ||
|
|
1f665e6ba8 | ||
|
|
d72217a00a | ||
|
|
261d3c892e | ||
|
|
2c50faf5b2 | ||
|
|
7dd0dd273e | ||
|
|
b462cfbe2b | ||
|
|
67b89eaa4f | ||
|
|
ed355d2eb6 | ||
|
|
c6d725d6e8 | ||
|
|
42230a4c51 | ||
|
|
7929aea45a | ||
|
|
f09d299660 | ||
|
|
41b3a372d3 | ||
|
|
7aaecacc5b | ||
|
|
237a05b302 | ||
|
|
f73c7f3be0 | ||
|
|
fe66d8bc04 | ||
|
|
26bd3e3811 | ||
|
|
0b7feb359d | ||
|
|
af4cf0d0ba | ||
|
|
4d561651a1 | ||
|
|
7e3265e7c7 | ||
|
|
822481d360 | ||
|
|
7905f2a972 | ||
|
|
88dc18f88a | ||
|
|
e685d59604 | ||
|
|
300df03743 | ||
|
|
a329007526 | ||
|
|
5784c7bacd | ||
|
|
db82ef3e61 | ||
|
|
ea52b3cc8f | ||
|
|
24a7a72f59 | ||
|
|
b1b17376ff | ||
|
|
c46d835146 | ||
|
|
20dc72ef9a | ||
|
|
e9c4f612cf | ||
|
|
34ad308599 | ||
|
|
9a75277dd4 | ||
|
|
003ab06465 | ||
|
|
36985ee704 | ||
|
|
21acb67b01 | ||
|
|
bda15231da | ||
|
|
5022b04ff9 | ||
|
|
6ed0ff0a12 | ||
|
|
789739f3e4 | ||
|
|
4f1af0114f | ||
|
|
5d1b4f98de | ||
|
|
706cc838e5 | ||
|
|
17cbb34952 | ||
|
|
1f50dee8a8 | ||
|
|
e126315c1b | ||
|
|
ccb5c57784 | ||
|
|
7a41a205ee | ||
|
|
8430aefe21 | ||
|
|
edfdbe10a0 | ||
|
|
108ceae313 | ||
|
|
e42a227a7c | ||
|
|
7e262dd42c | ||
|
|
ac175d2c40 | ||
|
|
c77dbd859b | ||
|
|
efe26d00a1 | ||
|
|
62755cc647 | ||
|
|
8c8a658dfd | ||
|
|
53ca54ced6 | ||
|
|
e757e3beaf | ||
|
|
5192306d39 | ||
|
|
4b98e3ea8e | ||
|
|
b7e522d7a7 | ||
|
|
6d27b4760f | ||
|
|
1b46208aa5 | ||
|
|
b3c01903b4 | ||
|
|
a04ba44874 | ||
|
|
9a8e8ce35d | ||
|
|
234d2e5f0f | ||
|
|
180078d0f6 | ||
|
|
38ad25ad4c | ||
|
|
1bc4b62805 | ||
|
|
7c7106b1c1 | ||
|
|
4677883acd | ||
|
|
8794d35867 | ||
|
|
595c19207c | ||
|
|
077ae9cee9 | ||
|
|
925f1c281c | ||
|
|
7d1fca1ca2 | ||
|
|
fd502631c7 | ||
|
|
60eb755fe9 | ||
|
|
a31289b9d7 | ||
|
|
112f9d1480 | ||
|
|
851f44a066 | ||
|
|
d9c8a9eecb | ||
|
|
03630df20d | ||
|
|
3d37e436dd | ||
|
|
32df9451fd | ||
|
|
e0b835178b | ||
|
|
78aa893efd | ||
|
|
8c7261e7c3 | ||
|
|
ae61272c13 | ||
|
|
67ae22b911 | ||
|
|
c0d26f2308 | ||
|
|
d58ae2ecda | ||
|
|
1d5fef4144 | ||
|
|
49195ebe17 | ||
|
|
9a33bd083d | ||
|
|
b2c7a9c7fc | ||
|
|
8b9f12d924 | ||
|
|
521705a0f2 | ||
|
|
c144df9be3 | ||
|
|
1eb7f92956 | ||
|
|
9125413786 | ||
|
|
afc9495b3f | ||
|
|
3eea19dcfa | ||
|
|
04ab0cd8fc | ||
|
|
b13c29944b | ||
|
|
68bb0c1ae1 | ||
|
|
a18a7bb678 | ||
|
|
834203d868 | ||
|
|
99c7924292 | ||
|
|
505d9e2154 | ||
|
|
bca927f861 | ||
|
|
70d2cbe857 | ||
|
|
dcf358f154 | ||
|
|
2b2d9e7a1d | ||
|
|
328a5fe49a | ||
|
|
839b6dd5e4 | ||
|
|
c988a99d55 | ||
|
|
a4a184b27c | ||
|
|
68a4099684 | ||
|
|
64088fce5d | ||
|
|
35a152318e | ||
|
|
3d0d31ddf8 | ||
|
|
c456f27f60 | ||
|
|
4ecb582c76 | ||
|
|
7390030854 | ||
|
|
da2dee03e2 | ||
|
|
9768d08458 | ||
|
|
a9fe9f43e9 | ||
|
|
61e2cdc6b0 | ||
|
|
60203af9b2 | ||
|
|
4532c2255a | ||
|
|
17c1ed948e | ||
|
|
266d85e917 | ||
|
|
4122abf558 | ||
|
|
f9c1464879 | ||
|
|
277e0aee8c | ||
|
|
957aefe69e | ||
|
|
3515df913f | ||
|
|
8869678c0f | ||
|
|
05f41278a6 | ||
|
|
961cb6e9a3 | ||
|
|
ed53f8aa74 | ||
|
|
be2e00c991 | ||
|
|
f1809ce180 | ||
|
|
549965b4b2 | ||
|
|
f70ee3a038 | ||
|
|
975d6ada66 | ||
|
|
a6e63d2676 | ||
|
|
c5593be7c9 | ||
|
|
65bbdc30de | ||
|
|
482ff2d009 | ||
|
|
fd44894e9a | ||
|
|
92ed05fc84 | ||
|
|
5d333045b9 | ||
|
|
bcafa19386 | ||
|
|
03698e4068 | ||
|
|
fdee7a9ae0 | ||
|
|
078e19d1c7 | ||
|
|
7a2c99353a | ||
|
|
3539b32629 | ||
|
|
247fc43cef | ||
|
|
a3cab174ca | ||
|
|
89e7e8623c | ||
|
|
cbfdf61976 | ||
|
|
3acc05d953 | ||
|
|
685e327b43 | ||
|
|
f572be92e2 | ||
|
|
75d59d8695 | ||
|
|
7c567b305a | ||
|
|
d3d9957fd4 | ||
|
|
c998797c55 | ||
|
|
78d4277e4b | ||
|
|
f3abf9a30a | ||
|
|
9177dc3d52 | ||
|
|
34b303845f | ||
|
|
c1edd5848f | ||
|
|
ed7ec261d0 | ||
|
|
a2cc9f0f6d | ||
|
|
2a005019bf | ||
|
|
c2bbaa9ead | ||
|
|
194a90923d | ||
|
|
e1ed0bf52a | ||
|
|
7112b551e2 | ||
|
|
3498f4d6ee | ||
|
|
8658376713 | ||
|
|
7a40e3f6f2 | ||
|
|
58019fbac0 | ||
|
|
2d27a99a0b | ||
|
|
337e2fa043 | ||
|
|
e7b4dca611 | ||
|
|
1d5b24ecc5 | ||
|
|
2d89ddfb1f | ||
|
|
eeca184836 | ||
|
|
1d2b2b2c8b | ||
|
|
26bb7978b5 | ||
|
|
aa6ac3d6b0 | ||
|
|
1720527f81 | ||
|
|
fe672d2f61 | ||
|
|
d488e84d8d | ||
|
|
a4f88407c2 | ||
|
|
e46c65db09 | ||
|
|
6988b55f50 | ||
|
|
b736c4216c | ||
|
|
5bd8ffa53c | ||
|
|
1496250833 | ||
|
|
772e592489 | ||
|
|
fb44fa6b5a | ||
|
|
5799e391c6 | ||
|
|
e45c52b024 | ||
|
|
db936035e0 | ||
|
|
7b07a17886 | ||
|
|
e3a4c8ddeb | ||
|
|
013262a9b7 | ||
|
|
10f47389ae | ||
|
|
c697a2d47f |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,4 +1,3 @@
|
||||
build.properties
|
||||
build/
|
||||
logs/
|
||||
reports/
|
||||
@@ -7,3 +6,6 @@ download/
|
||||
lib/api/
|
||||
lib/Doctrine/Common
|
||||
lib/Doctrine/DBAL
|
||||
/.settings/
|
||||
.buildpath
|
||||
.project
|
||||
9
.gitmodules
vendored
9
.gitmodules
vendored
@@ -4,9 +4,12 @@
|
||||
[submodule "lib/vendor/doctrine-dbal"]
|
||||
path = lib/vendor/doctrine-dbal
|
||||
url = git://github.com/doctrine/dbal.git
|
||||
[submodule "lib/vendor/Symfony/Component/Yaml"]
|
||||
path = lib/vendor/Symfony/Component/Yaml
|
||||
url = git://github.com/symfony/Yaml.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 = git://github.com/doctrine/doctrine-build-common.git
|
||||
|
||||
19
.travis.yml
Normal file
19
.travis.yml
Normal file
@@ -0,0 +1,19 @@
|
||||
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
|
||||
523
LICENSE
523
LICENSE
@@ -1,504 +1,19 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
not price. Our General Public Licenses are designed to make sure that
|
||||
you have the freedom to distribute copies of free software (and charge
|
||||
for this service if you wish); that you receive source code or can get
|
||||
it if you want it; that you can change the software and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
rights. These restrictions translate to certain responsibilities for
|
||||
you if you distribute copies of the library or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link other code with the library, you must provide
|
||||
complete object files to the recipients, so that they can relink them
|
||||
with the library after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser General Public License (also called "this License").
|
||||
Each licensee is addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also combine or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
d) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
e) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the materials to be distributed need not include anything that is
|
||||
normally distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties with
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Lesser General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
||||
|
||||
|
||||
Copyright (c) 2006-2012 Doctrine Project
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
@@ -1,14 +1,19 @@
|
||||
# Doctrine 2 ORM
|
||||
|
||||
Doctrine 2 is an object-relational mapper (ORM) for PHP 5.3.0+ that provides transparent persistence
|
||||
Master: [](http://travis-ci.org/doctrine/doctrine2)
|
||||
2.2: [](http://travis-ci.org/doctrine/doctrine2)
|
||||
2.1: [](http://travis-ci.org/doctrine/doctrine2)
|
||||
|
||||
Doctrine 2 is an object-relational mapper (ORM) for PHP 5.3.2+ that provides transparent persistence
|
||||
for PHP objects. It sits on top of a powerful database abstraction layer (DBAL). One of its key features
|
||||
is the option to write database queries in a proprietary object oriented SQL dialect called Doctrine Query Language (DQL),
|
||||
inspired by Hibernates HQL. This provides developers with a powerful alternative to SQL that maintains flexibility
|
||||
without requiring unnecessary code duplication.
|
||||
|
||||
More resources:
|
||||
## More resources:
|
||||
|
||||
* [Website](http://www.doctrine-project.org)
|
||||
* [Documentation](http://www.doctrine-project.org/projects/orm/2.0/docs/reference/introduction/en)
|
||||
* [Documentation](http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/index.html)
|
||||
* [Issue Tracker](http://www.doctrine-project.org/jira/browse/DDC)
|
||||
* [Downloads](http://github.com/doctrine/doctrine2/downloads)
|
||||
* [Downloads](http://github.com/doctrine/doctrine2/downloads)
|
||||
|
||||
|
||||
467
UPGRADE.md
Normal file
467
UPGRADE.md
Normal file
@@ -0,0 +1,467 @@
|
||||
# Upgrade to 2.3
|
||||
|
||||
## EntityGenerator add*() method generation
|
||||
|
||||
When generating an add*() method for a collection the EntityGenerator will now not
|
||||
use the Type-Hint to get the singular for the collection name, but use the field-name
|
||||
and strip a trailing "s" character if there is one.
|
||||
|
||||
## Merge copies non persisted properties too
|
||||
|
||||
When merging an entity in UoW not only mapped properties are copied, but also others.
|
||||
|
||||
## Query, QueryBuilder and NativeQuery parameters *BC break*
|
||||
|
||||
From now on, parameters in queries is an ArrayCollection instead of a simple array.
|
||||
This affects heavily the usage of setParameters(), because it will not append anymore
|
||||
parameters to query, but will actually override the already defined ones.
|
||||
Whenever you are retrieving a parameter (ie. $query->getParameter(1)), you will
|
||||
receive an instance of Query\Parameter, which contains the methods "getName",
|
||||
"getValue" and "getType". Parameters are also only converted to when necessary, and
|
||||
not when they are set.
|
||||
|
||||
Also, related functions were affected:
|
||||
|
||||
* execute($parameters, $hydrationMode) the argument $parameters can be either an key=>value array or an ArrayCollection instance
|
||||
* iterate($parameters, $hydrationMode) the argument $parameters can be either an key=>value array or an ArrayCollection instance
|
||||
* setParameters($parameters) the argument $parameters can be either an key=>value array or an ArrayCollection instance
|
||||
* getParameters() now returns ArrayCollection instead of array
|
||||
* getParameter($key) now returns Parameter instance instead of parameter value
|
||||
|
||||
## Query TreeWalker method renamed
|
||||
|
||||
Internal changes were made to DQL and SQL generation. If you have implemented your own TreeWalker,
|
||||
you probably need to update it. The method walkJoinVariableDeclaration is now named walkJoin.
|
||||
|
||||
## Metadata Drivers
|
||||
|
||||
Metadata drivers have been rewritten to reuse code from Doctrine\Common. Anyone who is using the
|
||||
`Doctrine\ORM\Mapping\Driver\Driver` interface should instead refer to
|
||||
`Doctrine\Common\Persistence\Mapping\Driver\MappingDriver`. Same applies to
|
||||
`Doctrine\ORM\Mapping\Driver\AbstractFileDriver`: you should now refer to
|
||||
`Doctrine\Common\Persistence\Mapping\Driver\FileDriver`.
|
||||
|
||||
Also, following mapping drivers have been deprecated, please use their replacements in Doctrine\Common as listed:
|
||||
|
||||
* `Doctrine\ORM\Mapping\Driver\DriverChain` => `Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain`
|
||||
* `Doctrine\ORM\Mapping\Driver\PHPDriver` => `Doctrine\Common\Persistence\Mapping\Driver\PHPDriver`
|
||||
* `Doctrine\ORM\Mapping\Driver\StaticPHPDriver` => `Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver`
|
||||
|
||||
# Upgrade to 2.2
|
||||
|
||||
## ResultCache implementation rewritten
|
||||
|
||||
The result cache is completely rewritten and now works on the database result level, not inside the ORM AbstractQuery
|
||||
anymore. This means that for result cached queries the hydration will now always be performed again, regardless of
|
||||
the hydration mode. Affected areas are:
|
||||
|
||||
1. Fixes the problem that entities coming from the result cache were not registered in the UnitOfWork
|
||||
leading to problems during EntityManager#flush. Calls to EntityManager#merge are not necessary anymore.
|
||||
2. Affects the array hydrator which now includes the overhead of hydration compared to caching the final result.
|
||||
|
||||
The API is backwards compatible however most of the getter methods on the `AbstractQuery` object are now
|
||||
deprecated in favor of calling AbstractQuery#getQueryCacheProfile(). This method returns a `Doctrine\DBAL\Cache\QueryCacheProfile`
|
||||
instance with access to result cache driver, lifetime and cache key.
|
||||
|
||||
|
||||
## EntityManager#getPartialReference() creates read-only entity
|
||||
|
||||
Entities returned from EntityManager#getPartialReference() are now marked as read-only if they
|
||||
haven't been in the identity map before. This means objects of this kind never lead to changes
|
||||
in the UnitOfWork.
|
||||
|
||||
|
||||
## Fields omitted in a partial DQL query or a native query are never updated
|
||||
|
||||
Fields of an entity that are not returned from a partial DQL Query or native SQL query
|
||||
will never be updated through an UPDATE statement.
|
||||
|
||||
|
||||
## Removed support for onUpdate in @JoinColumn
|
||||
|
||||
The onUpdate foreign key handling makes absolutely no sense in an ORM. Additionally Oracle doesn't even support it. Support for it is removed.
|
||||
|
||||
|
||||
## Changes in Annotation Handling
|
||||
|
||||
There have been some changes to the annotation handling in Common 2.2 again, that affect how people with old configurations
|
||||
from 2.0 have to configure the annotation driver if they don't use `Configuration::newDefaultAnnotationDriver()`:
|
||||
|
||||
// Register the ORM Annotations in the AnnotationRegistry
|
||||
AnnotationRegistry::registerFile('path/to/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');
|
||||
|
||||
$reader = new \Doctrine\Common\Annotations\SimpleAnnotationReader();
|
||||
$reader->addNamespace('Doctrine\ORM\Mapping');
|
||||
$reader = new \Doctrine\Common\Annotations\CachedReader($reader, new ArrayCache());
|
||||
|
||||
$driver = new AnnotationDriver($reader, (array)$paths);
|
||||
|
||||
$config->setMetadataDriverImpl($driver);
|
||||
|
||||
|
||||
## Scalar mappings can now be ommitted from DQL result
|
||||
|
||||
You are now allowed to mark scalar SELECT expressions as HIDDEN an they are not hydrated anymore.
|
||||
Example:
|
||||
|
||||
SELECT u, SUM(a.id) AS HIDDEN numArticles FROM User u LEFT JOIN u.Articles a ORDER BY numArticles DESC HAVING numArticles > 10
|
||||
|
||||
Your result will be a collection of Users, and not an array with key 0 as User object instance and "numArticles" as the number of articles per user
|
||||
|
||||
|
||||
## Map entities as scalars in DQL result
|
||||
|
||||
When hydrating to array or even a mixed result in object hydrator, previously you had the 0 index holding you entity instance.
|
||||
You are now allowed to alias this, providing more flexibility for you code.
|
||||
Example:
|
||||
|
||||
SELECT u AS user FROM User u
|
||||
|
||||
Will now return a collection of arrays with index "user" pointing to the User object instance.
|
||||
|
||||
|
||||
## Performance optimizations
|
||||
|
||||
Thousands of lines were completely reviewed and optimized for best performance.
|
||||
Removed redundancy and improved code readability made now internal Doctrine code easier to understand.
|
||||
Also, Doctrine 2.2 now is around 10-15% faster than 2.1.
|
||||
|
||||
## EntityManager#find(null)
|
||||
|
||||
Previously EntityManager#find(null) returned null. It now throws an exception.
|
||||
|
||||
# Upgrade to 2.1
|
||||
|
||||
## Interface for EntityRepository
|
||||
|
||||
The EntityRepository now has an interface Doctrine\Common\Persistence\ObjectRepository. This means that your classes that override EntityRepository and extend find(), findOneBy() or findBy() must be adjusted to follow this interface.
|
||||
|
||||
## AnnotationReader changes
|
||||
|
||||
The annotation reader was heavily refactored between 2.0 and 2.1-RC1. In theory the operation of the new reader should be backwards compatible, but it has to be setup differently to work that way:
|
||||
|
||||
// new call to the AnnotationRegistry
|
||||
\Doctrine\Common\Annotations\AnnotationRegistry::registerFile('/doctrine-src/lib/Doctrine/ORM/Mapping/Driver/DoctrineAnnotations.php');
|
||||
|
||||
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
|
||||
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
|
||||
// new code necessary starting here
|
||||
$reader->setIgnoreNotImportedAnnotations(true);
|
||||
$reader->setEnableParsePhpImports(false);
|
||||
$reader = new \Doctrine\Common\Annotations\CachedReader(
|
||||
new \Doctrine\Common\Annotations\IndexedReader($reader), new ArrayCache()
|
||||
);
|
||||
|
||||
This is already done inside the ``$config->newDefaultAnnotationDriver``, so everything should automatically work if you are using this method. You can verify if everything still works by executing a console command such as schema-validate that loads all metadata into memory.
|
||||
|
||||
# Update from 2.0-BETA3 to 2.0-BETA4
|
||||
|
||||
## XML Driver <change-tracking-policy /> element demoted to attribute
|
||||
|
||||
We changed how the XML Driver allows to define the change-tracking-policy. The working case is now:
|
||||
|
||||
<entity change-tracking-policy="DEFERRED_IMPLICT" />
|
||||
|
||||
# Update from 2.0-BETA2 to 2.0-BETA3
|
||||
|
||||
## Serialization of Uninitialized Proxies
|
||||
|
||||
As of Beta3 you can now serialize uninitialized proxies, an exception will only be thrown when
|
||||
trying to access methods on the unserialized proxy as long as it has not been re-attached to the
|
||||
EntityManager using `EntityManager#merge()`. See this example:
|
||||
|
||||
$proxy = $em->getReference('User', 1);
|
||||
|
||||
$serializedProxy = serialize($proxy);
|
||||
$detachedProxy = unserialized($serializedProxy);
|
||||
|
||||
echo $em->contains($detachedProxy); // FALSE
|
||||
|
||||
try {
|
||||
$detachedProxy->getId(); // uninitialized detached proxy
|
||||
} catch(Exception $e) {
|
||||
|
||||
}
|
||||
$attachedProxy = $em->merge($detachedProxy);
|
||||
echo $attackedProxy->getId(); // works!
|
||||
|
||||
## Changed SQL implementation of Postgres and Oracle DateTime types
|
||||
|
||||
The DBAL Type "datetime" included the Timezone Offset in both Postgres and Oracle. As of this version they are now
|
||||
generated without Timezone (TIMESTAMP WITHOUT TIME ZONE instead of TIMESTAMP WITH TIME ZONE).
|
||||
See [this comment to Ticket DBAL-22](http://www.doctrine-project.org/jira/browse/DBAL-22?focusedCommentId=13396&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_13396)
|
||||
for more details as well as migration issues for PostgreSQL and Oracle.
|
||||
|
||||
Both Postgres and Oracle will throw Exceptions during hydration of Objects with "DateTime" fields unless migration steps are taken!
|
||||
|
||||
## Removed multi-dot/deep-path expressions in DQL
|
||||
|
||||
The support for implicit joins in DQL through the multi-dot/Deep Path Expressions
|
||||
was dropped. For example:
|
||||
|
||||
SELECT u FROM User u WHERE u.group.name = ?1
|
||||
|
||||
See the "u.group.id" here is using multi dots (deep expression) to walk
|
||||
through the graph of objects and properties. Internally the DQL parser
|
||||
would rewrite these queries to:
|
||||
|
||||
SELECT u FROM User u JOIN u.group g WHERE g.name = ?1
|
||||
|
||||
This explicit notation will be the only supported notation as of now. The internal
|
||||
handling of multi-dots in the DQL Parser was very complex, error prone in edge cases
|
||||
and required special treatment for several features we added. Additionally
|
||||
it had edge cases that could not be solved without making the DQL Parser
|
||||
even much more complex. For this reason we will drop the support for the
|
||||
deep path expressions to increase maintainability and overall performance
|
||||
of the DQL parsing process. This will benefit any DQL query being parsed,
|
||||
even those not using deep path expressions.
|
||||
|
||||
Note that the generated SQL of both notations is exactly the same! You
|
||||
don't loose anything through this.
|
||||
|
||||
## Default Allocation Size for Sequences
|
||||
|
||||
The default allocation size for sequences has been changed from 10 to 1. This step was made
|
||||
to not cause confusion with users and also because it is partly some kind of premature optimization.
|
||||
|
||||
# Update from 2.0-BETA1 to 2.0-BETA2
|
||||
|
||||
There are no backwards incompatible changes in this release.
|
||||
|
||||
# Upgrade from 2.0-ALPHA4 to 2.0-BETA1
|
||||
|
||||
## EntityRepository deprecates access to protected variables
|
||||
|
||||
Instead of accessing protected variables for the EntityManager in
|
||||
a custom EntityRepository it is now required to use the getter methods
|
||||
for all the three instance variables:
|
||||
|
||||
* `$this->_em` now accessible through `$this->getEntityManager()`
|
||||
* `$this->_class` now accessible through `$this->getClassMetadata()`
|
||||
* `$this->_entityName` now accessible through `$this->getEntityName()`
|
||||
|
||||
Important: For Beta 2 the protected visibility of these three properties will be
|
||||
changed to private!
|
||||
|
||||
## Console migrated to Symfony Console
|
||||
|
||||
The Doctrine CLI has been replaced by Symfony Console Configuration
|
||||
|
||||
Instead of having to specify:
|
||||
|
||||
[php]
|
||||
$cliConfig = new CliConfiguration();
|
||||
$cliConfig->setAttribute('em', $entityManager);
|
||||
|
||||
You now have to configure the script like:
|
||||
|
||||
[php]
|
||||
$helperSet = new \Symfony\Components\Console\Helper\HelperSet(array(
|
||||
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
|
||||
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
|
||||
));
|
||||
|
||||
## Console: No need for Mapping Paths anymore
|
||||
|
||||
In previous versions you had to specify the --from and --from-path options
|
||||
to show where your mapping paths are from the console. However this information
|
||||
is already known from the Mapping Driver configuration, so the requirement
|
||||
for this options were dropped.
|
||||
|
||||
Instead for each console command all the entities are loaded and to
|
||||
restrict the operation to one or more sub-groups you can use the --filter flag.
|
||||
|
||||
## AnnotationDriver is not a default mapping driver anymore
|
||||
|
||||
In conjunction with the recent changes to Console we realized that the
|
||||
annotations driver being a default metadata driver lead to lots of glue
|
||||
code in the console components to detect where entities lie and how to load
|
||||
them for batch updates like SchemaTool and other commands. However the
|
||||
annotations driver being a default driver does not really help that much
|
||||
anyways.
|
||||
|
||||
Therefore we decided to break backwards compability in this issue and drop
|
||||
the support for Annotations as Default Driver and require our users to
|
||||
specify the driver explicitly (which allows us to ask for the path to all
|
||||
entities).
|
||||
|
||||
If you are using the annotations metadata driver as default driver, you
|
||||
have to add the following lines to your bootstrap code:
|
||||
|
||||
$driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__."/Entities"));
|
||||
$config->setMetadataDriverImpl($driverImpl);
|
||||
|
||||
You have to specify the path to your entities as either string of a single
|
||||
path or array of multiple paths
|
||||
to your entities. This information will be used by all console commands to
|
||||
access all entities.
|
||||
|
||||
Xml and Yaml Drivers work as before!
|
||||
|
||||
|
||||
## New inversedBy attribute
|
||||
|
||||
It is now *mandatory* that the owning side of a bidirectional association specifies the
|
||||
'inversedBy' attribute that points to the name of the field on the inverse side that completes
|
||||
the association. Example:
|
||||
|
||||
[php]
|
||||
// BEFORE (ALPHA4 AND EARLIER)
|
||||
class User
|
||||
{
|
||||
//...
|
||||
/** @OneToOne(targetEntity="Address", mappedBy="user") */
|
||||
private $address;
|
||||
//...
|
||||
}
|
||||
class Address
|
||||
{
|
||||
//...
|
||||
/** @OneToOne(targetEntity="User") */
|
||||
private $user;
|
||||
//...
|
||||
}
|
||||
|
||||
// SINCE BETA1
|
||||
// User class DOES NOT CHANGE
|
||||
class Address
|
||||
{
|
||||
//...
|
||||
/** @OneToOne(targetEntity="User", inversedBy="address") */
|
||||
private $user;
|
||||
//...
|
||||
}
|
||||
|
||||
Thus, the inversedBy attribute is the counterpart to the mappedBy attribute. This change
|
||||
was necessary to enable some simplifications and further performance improvements. We
|
||||
apologize for the inconvenience.
|
||||
|
||||
## Default Property for Field Mappings
|
||||
|
||||
The "default" option for database column defaults has been removed. If desired, database column defaults can
|
||||
be implemented by using the columnDefinition attribute of the @Column annotation (or the approriate XML and YAML equivalents).
|
||||
Prefer PHP default values, if possible.
|
||||
|
||||
## Selecting Partial Objects
|
||||
|
||||
Querying for partial objects now has a new syntax. The old syntax to query for partial objects
|
||||
now has a different meaning. This is best illustrated by an example. If you previously
|
||||
had a DQL query like this:
|
||||
|
||||
[sql]
|
||||
SELECT u.id, u.name FROM User u
|
||||
|
||||
Since BETA1, simple state field path expressions in the select clause are used to select
|
||||
object fields as plain scalar values (something that was not possible before).
|
||||
To achieve the same result as previously (that is, a partial object with only id and name populated)
|
||||
you need to use the following, explicit syntax:
|
||||
|
||||
[sql]
|
||||
SELECT PARTIAL u.{id,name} FROM User u
|
||||
|
||||
## XML Mapping Driver
|
||||
|
||||
The 'inheritance-type' attribute changed to take last bit of ClassMetadata constant names, i.e.
|
||||
NONE, SINGLE_TABLE, INHERITANCE_TYPE_JOINED
|
||||
|
||||
## YAML Mapping Driver
|
||||
|
||||
The way to specify lifecycle callbacks in YAML Mapping driver was changed to allow for multiple callbacks
|
||||
per event. The Old syntax ways:
|
||||
|
||||
[yaml]
|
||||
lifecycleCallbacks:
|
||||
doStuffOnPrePersist: prePersist
|
||||
doStuffOnPostPersist: postPersist
|
||||
|
||||
The new syntax is:
|
||||
|
||||
[yaml]
|
||||
lifecycleCallbacks:
|
||||
prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ]
|
||||
postPersist: [ doStuffOnPostPersist ]
|
||||
|
||||
## PreUpdate Event Listeners
|
||||
|
||||
Event Listeners listening to the 'preUpdate' event can only affect the primitive values of entity changesets
|
||||
by using the API on the `PreUpdateEventArgs` instance passed to the preUpdate listener method. Any changes
|
||||
to the state of the entitys properties won't affect the database UPDATE statement anymore. This gives drastic
|
||||
performance benefits for the preUpdate event.
|
||||
|
||||
## Collection API
|
||||
|
||||
The Collection interface in the Common package has been updated with some missing methods
|
||||
that were present only on the default implementation, ArrayCollection. Custom collection
|
||||
implementations need to be updated to adhere to the updated interface.
|
||||
|
||||
# Upgrade from 2.0-ALPHA3 to 2.0-ALPHA4
|
||||
|
||||
## CLI Controller changes
|
||||
|
||||
CLI main object changed its name and namespace. Renamed from Doctrine\ORM\Tools\Cli to Doctrine\Common\Cli\CliController.
|
||||
Doctrine\Common\Cli\CliController now only deals with namespaces. Ready to go, Core, Dbal and Orm are available and you can subscribe new tasks by retrieving the namespace and including new task. Example:
|
||||
|
||||
[php]
|
||||
$cli->getNamespace('Core')->addTask('my-example', '\MyProject\Tools\Cli\Tasks\MyExampleTask');
|
||||
|
||||
|
||||
## CLI Tasks documentation
|
||||
|
||||
Tasks have implemented a new way to build documentation. Although it is still possible to define the help manually by extending the basicHelp and extendedHelp, they are now optional.
|
||||
With new required method AbstractTask::buildDocumentation, its implementation defines the TaskDocumentation instance (accessible through AbstractTask::getDocumentation()), basicHelp and extendedHelp are now not necessary to be implemented.
|
||||
|
||||
## Changes in Method Signatures
|
||||
|
||||
* A bunch of Methods on both Doctrine\DBAL\Platforms\AbstractPlatform and Doctrine\DBAL\Schema\AbstractSchemaManager
|
||||
have changed quite significantly by adopting the new Schema instance objects.
|
||||
|
||||
## Renamed Methods
|
||||
|
||||
* Doctrine\ORM\AbstractQuery::setExpireResultCache() -> expireResultCache()
|
||||
* Doctrine\ORM\Query::setExpireQueryCache() -> expireQueryCache()
|
||||
|
||||
## SchemaTool Changes
|
||||
|
||||
* "doctrine schema-tool --drop" now always drops the complete database instead of
|
||||
only those tables defined by the current database model. The previous method had
|
||||
problems when foreign keys of orphaned tables pointed to tables that were schedulded
|
||||
for deletion.
|
||||
* Use "doctrine schema-tool --update" to get a save incremental update for your
|
||||
database schema without deleting any unused tables, sequences or foreign keys.
|
||||
* Use "doctrine schema-tool --complete-update" to do a full incremental update of
|
||||
your schema.
|
||||
# Upgrade from 2.0-ALPHA2 to 2.0-ALPHA3
|
||||
|
||||
This section details the changes made to Doctrine 2.0-ALPHA3 to make it easier for you
|
||||
to upgrade your projects to use this version.
|
||||
|
||||
## CLI Changes
|
||||
|
||||
The $args variable used in the cli-config.php for configuring the Doctrine CLI has been renamed to $globalArguments.
|
||||
|
||||
## Proxy class changes
|
||||
|
||||
You are now required to make supply some minimalist configuration with regards to proxy objects. That involves 2 new configuration options. First, the directory where generated proxy classes should be placed needs to be specified. Secondly, you need to configure the namespace used for proxy classes. The following snippet shows an example:
|
||||
|
||||
[php]
|
||||
// step 1: configure directory for proxy classes
|
||||
// $config instanceof Doctrine\ORM\Configuration
|
||||
$config->setProxyDir('/path/to/myproject/lib/MyProject/Generated/Proxies');
|
||||
$config->setProxyNamespace('MyProject\Generated\Proxies');
|
||||
|
||||
Note that proxy classes behave exactly like any other classes when it comes to class loading. Therefore you need to make sure the proxy classes can be loaded by some class loader. If you place the generated proxy classes in a namespace and directory under your projects class files, like in the example above, it would be sufficient to register the MyProject namespace on a class loader. Since the proxy classes are contained in that namespace and adhere to the standards for class loading, no additional work is required.
|
||||
Generating the proxy classes into a namespace within your class library is the recommended setup.
|
||||
|
||||
Entities with initialized proxy objects can now be serialized and unserialized properly from within the same application.
|
||||
|
||||
For more details refer to the Configuration section of the manual.
|
||||
|
||||
## Removed allowPartialObjects configuration option
|
||||
|
||||
The allowPartialObjects configuration option together with the `Configuration#getAllowPartialObjects` and `Configuration#setAllowPartialObjects` methods have been removed.
|
||||
The new behavior is as if the option were set to FALSE all the time, basically disallowing partial objects globally. However, you can still use the `Query::HINT_FORCE_PARTIAL_LOAD` query hint to force a query to return partial objects for optimization purposes.
|
||||
|
||||
## Renamed Methods
|
||||
|
||||
* Doctrine\ORM\Configuration#getCacheDir() to getProxyDir()
|
||||
* Doctrine\ORM\Configuration#setCacheDir($dir) to setProxyDir($dir)
|
||||
240
UPGRADE_TO_2_0
240
UPGRADE_TO_2_0
@@ -1,240 +0,0 @@
|
||||
# Update from 2.0-BETA3 to 2.0-BETA4
|
||||
|
||||
## XML Driver <change-tracking-policy /> element demoted to attribute
|
||||
|
||||
We changed how the XML Driver allows to define the change-tracking-policy. The working case is now:
|
||||
|
||||
<entity change-tracking-policy="DEFERRED_IMPLICT" />
|
||||
|
||||
# Update from 2.0-BETA2 to 2.0-BETA3
|
||||
|
||||
## Serialization of Uninitialized Proxies
|
||||
|
||||
As of Beta3 you can now serialize uninitialized proxies, an exception will only be thrown when
|
||||
trying to access methods on the unserialized proxy as long as it has not been re-attached to the
|
||||
EntityManager using `EntityManager#merge()`. See this example:
|
||||
|
||||
$proxy = $em->getReference('User', 1);
|
||||
|
||||
$serializedProxy = serialize($proxy);
|
||||
$detachedProxy = unserialized($serializedProxy);
|
||||
|
||||
echo $em->contains($detachedProxy); // FALSE
|
||||
|
||||
try {
|
||||
$detachedProxy->getId(); // uninitialized detached proxy
|
||||
} catch(Exception $e) {
|
||||
|
||||
}
|
||||
$attachedProxy = $em->merge($detachedProxy);
|
||||
echo $attackedProxy->getId(); // works!
|
||||
|
||||
## Changed SQL implementation of Postgres and Oracle DateTime types
|
||||
|
||||
The DBAL Type "datetime" included the Timezone Offset in both Postgres and Oracle. As of this version they are now
|
||||
generated without Timezone (TIMESTAMP WITHOUT TIME ZONE instead of TIMESTAMP WITH TIME ZONE).
|
||||
See [this comment to Ticket DBAL-22](http://www.doctrine-project.org/jira/browse/DBAL-22?focusedCommentId=13396&page=com.atlassian.jira.plugin.system.issuetabpanels%3Acomment-tabpanel#action_13396)
|
||||
for more details as well as migration issues for PostgreSQL and Oracle.
|
||||
|
||||
Both Postgres and Oracle will throw Exceptions during hydration of Objects with "DateTime" fields unless migration steps are taken!
|
||||
|
||||
## Removed multi-dot/deep-path expressions in DQL
|
||||
|
||||
The support for implicit joins in DQL through the multi-dot/Deep Path Expressions
|
||||
was dropped. For example:
|
||||
|
||||
SELECT u FROM User u WHERE u.group.name = ?1
|
||||
|
||||
See the "u.group.id" here is using multi dots (deep expression) to walk
|
||||
through the graph of objects and properties. Internally the DQL parser
|
||||
would rewrite these queries to:
|
||||
|
||||
SELECT u FROM User u JOIN u.group g WHERE g.name = ?1
|
||||
|
||||
This explicit notation will be the only supported notation as of now. The internal
|
||||
handling of multi-dots in the DQL Parser was very complex, error prone in edge cases
|
||||
and required special treatment for several features we added. Additionally
|
||||
it had edge cases that could not be solved without making the DQL Parser
|
||||
even much more complex. For this reason we will drop the support for the
|
||||
deep path expressions to increase maintainability and overall performance
|
||||
of the DQL parsing process. This will benefit any DQL query being parsed,
|
||||
even those not using deep path expressions.
|
||||
|
||||
Note that the generated SQL of both notations is exactly the same! You
|
||||
don't loose anything through this.
|
||||
|
||||
## Default Allocation Size for Sequences
|
||||
|
||||
The default allocation size for sequences has been changed from 10 to 1. This step was made
|
||||
to not cause confusion with users and also because it is partly some kind of premature optimization.
|
||||
|
||||
# Update from 2.0-BETA1 to 2.0-BETA2
|
||||
|
||||
There are no backwards incompatible changes in this release.
|
||||
|
||||
# Upgrade from 2.0-ALPHA4 to 2.0-BETA1
|
||||
|
||||
## EntityRepository deprecates access to protected variables
|
||||
|
||||
Instead of accessing protected variables for the EntityManager in
|
||||
a custom EntityRepository it is now required to use the getter methods
|
||||
for all the three instance variables:
|
||||
|
||||
* `$this->_em` now accessible through `$this->getEntityManager()`
|
||||
* `$this->_class` now accessible through `$this->getClassMetadata()`
|
||||
* `$this->_entityName` now accessible through `$this->getEntityName()`
|
||||
|
||||
Important: For Beta 2 the protected visibility of these three properties will be
|
||||
changed to private!
|
||||
|
||||
## Console migrated to Symfony Console
|
||||
|
||||
The Doctrine CLI has been replaced by Symfony Console Configuration
|
||||
|
||||
Instead of having to specify:
|
||||
|
||||
[php]
|
||||
$cliConfig = new CliConfiguration();
|
||||
$cliConfig->setAttribute('em', $entityManager);
|
||||
|
||||
You now have to configure the script like:
|
||||
|
||||
[php]
|
||||
$helperSet = new \Symfony\Components\Console\Helper\HelperSet(array(
|
||||
'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),
|
||||
'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)
|
||||
));
|
||||
|
||||
## Console: No need for Mapping Paths anymore
|
||||
|
||||
In previous versions you had to specify the --from and --from-path options
|
||||
to show where your mapping paths are from the console. However this information
|
||||
is already known from the Mapping Driver configuration, so the requirement
|
||||
for this options were dropped.
|
||||
|
||||
Instead for each console command all the entities are loaded and to
|
||||
restrict the operation to one or more sub-groups you can use the --filter flag.
|
||||
|
||||
## AnnotationDriver is not a default mapping driver anymore
|
||||
|
||||
In conjunction with the recent changes to Console we realized that the
|
||||
annotations driver being a default metadata driver lead to lots of glue
|
||||
code in the console components to detect where entities lie and how to load
|
||||
them for batch updates like SchemaTool and other commands. However the
|
||||
annotations driver being a default driver does not really help that much
|
||||
anyways.
|
||||
|
||||
Therefore we decided to break backwards compability in this issue and drop
|
||||
the support for Annotations as Default Driver and require our users to
|
||||
specify the driver explicitly (which allows us to ask for the path to all
|
||||
entities).
|
||||
|
||||
If you are using the annotations metadata driver as default driver, you
|
||||
have to add the following lines to your bootstrap code:
|
||||
|
||||
$driverImpl = $config->newDefaultAnnotationDriver(array(__DIR__."/Entities"));
|
||||
$config->setMetadataDriverImpl($driverImpl);
|
||||
|
||||
You have to specify the path to your entities as either string of a single
|
||||
path or array of multiple paths
|
||||
to your entities. This information will be used by all console commands to
|
||||
access all entities.
|
||||
|
||||
Xml and Yaml Drivers work as before!
|
||||
|
||||
|
||||
## New inversedBy attribute
|
||||
|
||||
It is now *mandatory* that the owning side of a bidirectional association specifies the
|
||||
'inversedBy' attribute that points to the name of the field on the inverse side that completes
|
||||
the association. Example:
|
||||
|
||||
[php]
|
||||
// BEFORE (ALPHA4 AND EARLIER)
|
||||
class User
|
||||
{
|
||||
//...
|
||||
/** @OneToOne(targetEntity="Address", mappedBy="user") */
|
||||
private $address;
|
||||
//...
|
||||
}
|
||||
class Address
|
||||
{
|
||||
//...
|
||||
/** @OneToOne(targetEntity="User") */
|
||||
private $user;
|
||||
//...
|
||||
}
|
||||
|
||||
// SINCE BETA1
|
||||
// User class DOES NOT CHANGE
|
||||
class Address
|
||||
{
|
||||
//...
|
||||
/** @OneToOne(targetEntity="User", inversedBy="address") */
|
||||
private $user;
|
||||
//...
|
||||
}
|
||||
|
||||
Thus, the inversedBy attribute is the counterpart to the mappedBy attribute. This change
|
||||
was necessary to enable some simplifications and further performance improvements. We
|
||||
apologize for the inconvenience.
|
||||
|
||||
## Default Property for Field Mappings
|
||||
|
||||
The "default" option for database column defaults has been removed. If desired, database column defaults can
|
||||
be implemented by using the columnDefinition attribute of the @Column annotation (or the approriate XML and YAML equivalents).
|
||||
Prefer PHP default values, if possible.
|
||||
|
||||
## Selecting Partial Objects
|
||||
|
||||
Querying for partial objects now has a new syntax. The old syntax to query for partial objects
|
||||
now has a different meaning. This is best illustrated by an example. If you previously
|
||||
had a DQL query like this:
|
||||
|
||||
[sql]
|
||||
SELECT u.id, u.name FROM User u
|
||||
|
||||
Since BETA1, simple state field path expressions in the select clause are used to select
|
||||
object fields as plain scalar values (something that was not possible before).
|
||||
To achieve the same result as previously (that is, a partial object with only id and name populated)
|
||||
you need to use the following, explicit syntax:
|
||||
|
||||
[sql]
|
||||
SELECT PARTIAL u.{id,name} FROM User u
|
||||
|
||||
## XML Mapping Driver
|
||||
|
||||
The 'inheritance-type' attribute changed to take last bit of ClassMetadata constant names, i.e.
|
||||
NONE, SINGLE_TABLE, INHERITANCE_TYPE_JOINED
|
||||
|
||||
## YAML Mapping Driver
|
||||
|
||||
The way to specify lifecycle callbacks in YAML Mapping driver was changed to allow for multiple callbacks
|
||||
per event. The Old syntax ways:
|
||||
|
||||
[yaml]
|
||||
lifecycleCallbacks:
|
||||
doStuffOnPrePersist: prePersist
|
||||
doStuffOnPostPersist: postPersist
|
||||
|
||||
The new syntax is:
|
||||
|
||||
[yaml]
|
||||
lifecycleCallbacks:
|
||||
prePersist: [ doStuffOnPrePersist, doOtherStuffOnPrePersistToo ]
|
||||
postPersist: [ doStuffOnPostPersist ]
|
||||
|
||||
## PreUpdate Event Listeners
|
||||
|
||||
Event Listeners listening to the 'preUpdate' event can only affect the primitive values of entity changesets
|
||||
by using the API on the `PreUpdateEventArgs` instance passed to the preUpdate listener method. Any changes
|
||||
to the state of the entitys properties won't affect the database UPDATE statement anymore. This gives drastic
|
||||
performance benefits for the preUpdate event.
|
||||
|
||||
## Collection API
|
||||
|
||||
The Collection interface in the Common package has been updated with some missing methods
|
||||
that were present only on the default implementation, ArrayCollection. Custom collection
|
||||
implementations need to be updated to adhere to the updated interface.
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
# Upgrade from 2.0-ALPHA2 to 2.0-ALPHA3
|
||||
|
||||
This section details the changes made to Doctrine 2.0-ALPHA3 to make it easier for you
|
||||
to upgrade your projects to use this version.
|
||||
|
||||
## CLI Changes
|
||||
|
||||
The $args variable used in the cli-config.php for configuring the Doctrine CLI has been renamed to $globalArguments.
|
||||
|
||||
## Proxy class changes
|
||||
|
||||
You are now required to make supply some minimalist configuration with regards to proxy objects. That involves 2 new configuration options. First, the directory where generated proxy classes should be placed needs to be specified. Secondly, you need to configure the namespace used for proxy classes. The following snippet shows an example:
|
||||
|
||||
[php]
|
||||
// step 1: configure directory for proxy classes
|
||||
// $config instanceof Doctrine\ORM\Configuration
|
||||
$config->setProxyDir('/path/to/myproject/lib/MyProject/Generated/Proxies');
|
||||
$config->setProxyNamespace('MyProject\Generated\Proxies');
|
||||
|
||||
Note that proxy classes behave exactly like any other classes when it comes to class loading. Therefore you need to make sure the proxy classes can be loaded by some class loader. If you place the generated proxy classes in a namespace and directory under your projects class files, like in the example above, it would be sufficient to register the MyProject namespace on a class loader. Since the proxy classes are contained in that namespace and adhere to the standards for class loading, no additional work is required.
|
||||
Generating the proxy classes into a namespace within your class library is the recommended setup.
|
||||
|
||||
Entities with initialized proxy objects can now be serialized and unserialized properly from within the same application.
|
||||
|
||||
For more details refer to the Configuration section of the manual.
|
||||
|
||||
## Removed allowPartialObjects configuration option
|
||||
|
||||
The allowPartialObjects configuration option together with the `Configuration#getAllowPartialObjects` and `Configuration#setAllowPartialObjects` methods have been removed.
|
||||
The new behavior is as if the option were set to FALSE all the time, basically disallowing partial objects globally. However, you can still use the `Query::HINT_FORCE_PARTIAL_LOAD` query hint to force a query to return partial objects for optimization purposes.
|
||||
|
||||
## Renamed Methods
|
||||
|
||||
* Doctrine\ORM\Configuration#getCacheDir() to getProxyDir()
|
||||
* Doctrine\ORM\Configuration#setCacheDir($dir) to setProxyDir($dir)
|
||||
@@ -1,36 +0,0 @@
|
||||
# Upgrade from 2.0-ALPHA3 to 2.0-ALPHA4
|
||||
|
||||
## CLI Controller changes
|
||||
|
||||
CLI main object changed its name and namespace. Renamed from Doctrine\ORM\Tools\Cli to Doctrine\Common\Cli\CliController.
|
||||
Doctrine\Common\Cli\CliController now only deals with namespaces. Ready to go, Core, Dbal and Orm are available and you can subscribe new tasks by retrieving the namespace and including new task. Example:
|
||||
|
||||
[php]
|
||||
$cli->getNamespace('Core')->addTask('my-example', '\MyProject\Tools\Cli\Tasks\MyExampleTask');
|
||||
|
||||
|
||||
## CLI Tasks documentation
|
||||
|
||||
Tasks have implemented a new way to build documentation. Although it is still possible to define the help manually by extending the basicHelp and extendedHelp, they are now optional.
|
||||
With new required method AbstractTask::buildDocumentation, its implementation defines the TaskDocumentation instance (accessible through AbstractTask::getDocumentation()), basicHelp and extendedHelp are now not necessary to be implemented.
|
||||
|
||||
## Changes in Method Signatures
|
||||
|
||||
* A bunch of Methods on both Doctrine\DBAL\Platforms\AbstractPlatform and Doctrine\DBAL\Schema\AbstractSchemaManager
|
||||
have changed quite significantly by adopting the new Schema instance objects.
|
||||
|
||||
## Renamed Methods
|
||||
|
||||
* Doctrine\ORM\AbstractQuery::setExpireResultCache() -> expireResultCache()
|
||||
* Doctrine\ORM\Query::setExpireQueryCache() -> expireQueryCache()
|
||||
|
||||
## SchemaTool Changes
|
||||
|
||||
* "doctrine schema-tool --drop" now always drops the complete database instead of
|
||||
only those tables defined by the current database model. The previous method had
|
||||
problems when foreign keys of orphaned tables pointed to tables that were schedulded
|
||||
for deletion.
|
||||
* Use "doctrine schema-tool --update" to get a save incremental update for your
|
||||
database schema without deleting any unused tables, sequences or foreign keys.
|
||||
* Use "doctrine schema-tool --complete-update" to do a full incremental update of
|
||||
your schema.
|
||||
2
bin/doctrine
Normal file → Executable file
2
bin/doctrine
Normal file → Executable file
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
include('doctrine.php');
|
||||
include('doctrine.php');
|
||||
|
||||
50
bin/doctrine-pear.php
Normal file
50
bin/doctrine-pear.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?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>.
|
||||
*/
|
||||
|
||||
require_once 'Doctrine/Common/ClassLoader.php';
|
||||
|
||||
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine');
|
||||
$classLoader->register();
|
||||
|
||||
$classLoader = new \Doctrine\Common\ClassLoader('Symfony');
|
||||
$classLoader->register();
|
||||
|
||||
$configFile = getcwd() . DIRECTORY_SEPARATOR . 'cli-config.php';
|
||||
|
||||
$helperSet = null;
|
||||
if (file_exists($configFile)) {
|
||||
if ( ! is_readable($configFile)) {
|
||||
trigger_error(
|
||||
'Configuration file [' . $configFile . '] does not have read permission.', E_ERROR
|
||||
);
|
||||
}
|
||||
|
||||
require $configFile;
|
||||
|
||||
foreach ($GLOBALS as $helperSetCandidate) {
|
||||
if ($helperSetCandidate instanceof \Symfony\Component\Console\Helper\HelperSet) {
|
||||
$helperSet = $helperSetCandidate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$helperSet = ($helperSet) ?: new \Symfony\Component\Console\Helper\HelperSet();
|
||||
|
||||
\Doctrine\ORM\Tools\Console\ConsoleRunner::run($helperSet);
|
||||
9
bin/doctrine.php
Normal file → Executable file
9
bin/doctrine.php
Normal file → Executable file
@@ -17,14 +17,7 @@
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
require_once 'Doctrine/Common/ClassLoader.php';
|
||||
|
||||
$classLoader = new \Doctrine\Common\ClassLoader('Doctrine');
|
||||
$classLoader->register();
|
||||
|
||||
$classLoader = new \Doctrine\Common\ClassLoader('Symfony', 'Doctrine');
|
||||
$classLoader->register();
|
||||
|
||||
(@include_once __DIR__ . '/../vendor/autoload.php') || @include_once __DIR__ . '/../../../autoload.php';
|
||||
$configFile = getcwd() . DIRECTORY_SEPARATOR . 'cli-config.php';
|
||||
|
||||
$helperSet = null;
|
||||
|
||||
11
build.properties
Normal file
11
build.properties
Normal file
@@ -0,0 +1,11 @@
|
||||
# Project Name
|
||||
project.name=DoctrineORM
|
||||
|
||||
# Dependency minimum versions
|
||||
dependencies.common=2.2.0beta1
|
||||
dependencies.dbal=2.2.0beta1
|
||||
dependencies.sfconsole=2.0.0
|
||||
|
||||
# Version class and file
|
||||
project.version_class = Doctrine\ORM\Version
|
||||
project.version_file = lib/Doctrine/ORM/Version.php
|
||||
@@ -1,6 +1,6 @@
|
||||
version=2.0.1
|
||||
dependencies.common=2.0.1
|
||||
dependencies.dbal=2.0.1
|
||||
version=2.0.0BETA2
|
||||
dependencies.common=2.0.0BETA4
|
||||
dependencies.dbal=2.0.0BETA4
|
||||
stability=beta
|
||||
build.dir=build
|
||||
dist.dir=dist
|
||||
@@ -8,6 +8,7 @@ report.dir=reports
|
||||
log.archive.dir=logs
|
||||
project.pirum_dir=
|
||||
project.download_dir=
|
||||
project.xsd_dir=
|
||||
test.phpunit_configuration_file=
|
||||
test.phpunit_generate_coverage=0
|
||||
test.pmd_reports=0
|
||||
|
||||
199
build.xml
199
build.xml
@@ -1,11 +1,7 @@
|
||||
<?xml version="1.0"?>
|
||||
|
||||
<!--
|
||||
Doctrine 2 build file.
|
||||
-->
|
||||
|
||||
<project name="Doctrine2" default="build" basedir=".">
|
||||
<project name="DoctrineORM" 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" />
|
||||
|
||||
@@ -14,6 +10,8 @@
|
||||
-->
|
||||
<fileset id="shared-artifacts" dir=".">
|
||||
<include name="LICENSE"/>
|
||||
<include name="UPGRADE*" />
|
||||
<include name="doctrine-mapping.xsd" />
|
||||
</fileset>
|
||||
|
||||
<!--
|
||||
@@ -21,7 +19,7 @@
|
||||
-->
|
||||
<fileset id="bin-scripts" dir="./bin">
|
||||
<include name="doctrine"/>
|
||||
<include name="doctrine.php"/>
|
||||
<include name="doctrine-pear.php"/>
|
||||
<include name="doctrine.bat"/>
|
||||
</fileset>
|
||||
|
||||
@@ -51,98 +49,34 @@
|
||||
-->
|
||||
<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="build-orm" depends="prepare">
|
||||
<exec command="grep '${version}' ${project.basedir}/lib/Doctrine/ORM/Version.php" checkreturn="true"/>
|
||||
<copy todir="${build.dir}/doctrine-orm">
|
||||
<target name="copy-files" depends="prepare">
|
||||
<copy todir="${build.dir}/${project.name}-${version}">
|
||||
<fileset refid="shared-artifacts"/>
|
||||
</copy>
|
||||
<copy todir="${build.dir}/doctrine-orm">
|
||||
<copy todir="${build.dir}/${project.name}-${version}">
|
||||
<fileset refid="common-sources"/>
|
||||
<fileset refid="dbal-sources"/>
|
||||
<fileset refid="orm-sources"/>
|
||||
</copy>
|
||||
<copy todir="${build.dir}/doctrine-orm/Doctrine">
|
||||
<copy todir="${build.dir}/${project.name}-${version}/Doctrine">
|
||||
<fileset refid="symfony-sources"/>
|
||||
</copy>
|
||||
<copy todir="${build.dir}/doctrine-orm/bin">
|
||||
<copy todir="${build.dir}/${project.name}-${version}/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" />
|
||||
</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="build-packages" depends="build-orm">
|
||||
<d51pearpkg2 baseinstalldir="/" dir="${build.dir}/doctrine-orm">
|
||||
<target name="define-pear-package" depends="copy-files">
|
||||
<d51pearpkg2 baseinstalldir="/" dir="${build.dir}/${project.name}-${version}">
|
||||
<name>DoctrineORM</name>
|
||||
<summary>Doctrine Object Relational Mapper</summary>
|
||||
<channel>pear.doctrine-project.org</channel>
|
||||
@@ -152,118 +86,29 @@
|
||||
<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="${version}" api="${version}" />
|
||||
<stability release="${stability}" api="${stability}" />
|
||||
<version release="${pear.version}" api="${pear.version}" />
|
||||
<stability release="${pear.stability}" api="${pear.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="DoctrineSymfonyConsole" channel="pear.doctrine-project.org" minimum_version="2.0.0" />
|
||||
<package name="DoctrineSymfonyYaml" channel="pear.doctrine-project.org" minimum_version="2.0.0" />
|
||||
<package name="Console" channel="pear.symfony.com" minimum_version="2.0.0" />
|
||||
<package name="Yaml" channel="pear.symfony.com" 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.php" name="bin/doctrine-pear.php" />
|
||||
<install as="doctrine.bat" name="bin/doctrine.bat" />
|
||||
</release>
|
||||
<replacement path="bin/doctrine.bat" type="pear-config" from="@php_bin@" to="php_bin" />
|
||||
<replacement path="bin/doctrine" 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>
|
||||
</project>
|
||||
|
||||
32
composer.json
Normal file
32
composer.json
Normal file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"name": "doctrine/orm",
|
||||
"type": "library","version":"2.3.0",
|
||||
"description": "Object-Relational-Mapper for PHP",
|
||||
"keywords": ["orm", "database"],
|
||||
"homepage": "http://www.doctrine-project.org",
|
||||
"license": "MIT",
|
||||
"authors": [
|
||||
{"name": "Guilherme Blanco", "email": "guilhermeblanco@gmail.com"},
|
||||
{"name": "Roman Borschel", "email": "roman@code-factory.org"},
|
||||
{"name": "Benjamin Eberlei", "email": "kontakt@beberlei.de"},
|
||||
{"name": "Jonathan Wage", "email": "jonwage@gmail.com"}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.2",
|
||||
"ext-pdo": "*",
|
||||
"doctrine/dbal": "2.3.*",
|
||||
"symfony/console": "2.*"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/yaml": "If you want to use YAML Metadata Mapping Driver"
|
||||
},
|
||||
"autoload": {
|
||||
"psr-0": { "Doctrine\\ORM": "lib/" }
|
||||
},
|
||||
"bin": ["bin/doctrine", "bin/doctrine.php"],
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.3.x-dev"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,11 +17,18 @@
|
||||
<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:complexType name="emptyType">
|
||||
<xs:sequence>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="cascade-type">
|
||||
<xs:sequence>
|
||||
@@ -30,7 +37,9 @@
|
||||
<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">
|
||||
@@ -46,29 +55,99 @@
|
||||
</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>
|
||||
|
||||
<xs:complexType name="named-native-query">
|
||||
<xs:attribute name="name" type="xs:string" use="required" />
|
||||
<xs:attribute name="query" type="xs:string" use="required"/>
|
||||
<xs:attribute name="result-class" type="xs:string" />
|
||||
<xs:attribute name="result-set-mapping" type="xs:string" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="named-native-queries">
|
||||
<xs:sequence>
|
||||
<xs:element name="named-native-query" type="orm:named-native-query" minOccurs="1" maxOccurs="unbounded" />
|
||||
<xs:any minOccurs="1" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="column-result">
|
||||
<xs:attribute name="name" type="xs:string" use="required" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="field-result">
|
||||
<xs:attribute name="name" type="xs:string" use="required" />
|
||||
<xs:attribute name="column" type="xs:string" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="entity-result">
|
||||
<xs:sequence>
|
||||
<xs:element name="field-result" type="orm:field-result" minOccurs="0" maxOccurs="unbounded" />
|
||||
</xs:sequence>
|
||||
<xs:attribute name="entity-class" type="xs:string" use="required" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="sql-result-set-mapping">
|
||||
<xs:sequence>
|
||||
<xs:element name="entity-result" type="orm:entity-result" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="column-result" type="orm:column-result" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:any minOccurs="1" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="sql-result-set-mappings">
|
||||
<xs:sequence>
|
||||
<xs:element name="sql-result-set-mapping" type="orm:sql-result-set-mapping" minOccurs="1" maxOccurs="unbounded" />
|
||||
<xs:any minOccurs="1" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="entity">
|
||||
<xs:sequence>
|
||||
<xs:element name="options" type="orm:options" minOccurs="0" />
|
||||
<xs:element name="indexes" type="orm:indexes" minOccurs="0"/>
|
||||
<xs:element name="unique-constraints" type="orm:unique-constraints" minOccurs="0"/>
|
||||
<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="id" type="orm:id" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="named-queries" type="orm:named-queries" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="named-native-queries" type="orm:named-native-queries" minOccurs="0" maxOccurs="1" />
|
||||
<xs:element name="id" type="orm:id" minOccurs="0" maxOccurs="unbounded" />
|
||||
<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:element name="association-overrides" type="orm:association-overrides" minOccurs="0" maxOccurs="unbounded" />
|
||||
<xs:element name="attribute-overrides" type="orm:attribute-overrides" 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" />
|
||||
@@ -76,11 +155,35 @@
|
||||
<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="option" mixed="true">
|
||||
<xs:sequence minOccurs="0" maxOccurs="unbounded">
|
||||
<xs:element name="option" type="orm:option"/>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="name" type="xs:NMTOKEN" use="required"/>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="options">
|
||||
<xs:sequence>
|
||||
<xs:element name="option" type="orm:option" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="mapped-superclass" >
|
||||
<xs:complexContent>
|
||||
<xs:extension base="orm:entity"/>
|
||||
<xs:extension base="orm:entity">
|
||||
<xs:sequence>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</xs:extension>
|
||||
</xs:complexContent>
|
||||
</xs:complexType>
|
||||
|
||||
@@ -106,6 +209,8 @@
|
||||
<xs:enumeration value="SEQUENCE"/>
|
||||
<xs:enumeration value="IDENTITY"/>
|
||||
<xs:enumeration value="AUTO"/>
|
||||
<xs:enumeration value="UUID"/>
|
||||
<xs:enumeration value="CUSTOM" />
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
@@ -113,7 +218,7 @@
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="CASCADE"/>
|
||||
<xs:enumeration value="RESTRICT"/>
|
||||
<xs:enumeration value="SET_NULL"/>
|
||||
<xs:enumeration value="SET NULL"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
@@ -121,10 +226,15 @@
|
||||
<xs:restriction base="xs:token">
|
||||
<xs:enumeration value="EAGER"/>
|
||||
<xs:enumeration value="LAZY"/>
|
||||
<xs:enumeration value="EXTRA_LAZY"/>
|
||||
</xs:restriction>
|
||||
</xs:simpleType>
|
||||
|
||||
<xs:complexType name="field">
|
||||
<xs:sequence>
|
||||
<xs:element name="options" type="orm:options" minOccurs="0" />
|
||||
<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" />
|
||||
@@ -135,75 +245,124 @@
|
||||
<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="type" type="xs:NMTOKEN"/>
|
||||
<xs:attribute name="field-name" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="length" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="column-definition" type="xs:string" />
|
||||
<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:NMTOKENS" use="required"/>
|
||||
<xs:attribute name="columns" type="xs:string" use="required"/>
|
||||
<xs:anyAttribute namespace="##other"/>
|
||||
</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: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:element name="custom-id-generator" type="orm:custom-id-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" use="required" />
|
||||
<xs:attribute name="type" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="column" type="xs:NMTOKEN" />
|
||||
<xs:attribute name="association-key" type="xs:boolean" default="false" />
|
||||
<xs:attribute name="column-definition" type="xs:string" />
|
||||
<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="custom-id-generator">
|
||||
<xs:sequence>
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="class" type="xs:NMTOKEN" use="required" />
|
||||
</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" />
|
||||
@@ -211,32 +370,43 @@
|
||||
<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:attribute name="name" type="xs:NMTOKEN" use="required" />
|
||||
<xs:attribute name="direction" type="orm:order-by-direction" default="ASC" />
|
||||
<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:complexType>
|
||||
|
||||
<xs:simpleType name="order-by-direction">
|
||||
@@ -251,24 +421,31 @@
|
||||
<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:attribute name="orphan-removal" type="xs:boolean" default="false" />
|
||||
<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">
|
||||
@@ -277,13 +454,16 @@
|
||||
<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">
|
||||
@@ -292,7 +472,9 @@
|
||||
<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" />
|
||||
@@ -300,6 +482,38 @@
|
||||
<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:complexType name="association-overrides">
|
||||
<xs:sequence>
|
||||
<xs:element name="association-override" type="orm:association-override" minOccurs="1" maxOccurs="unbounded" />
|
||||
<xs:any minOccurs="1" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="association-override">
|
||||
<xs:sequence>
|
||||
<xs:element name="join-table" type="orm:join-table" minOccurs="0" />
|
||||
<xs:element name="join-columns" type="orm:join-columns" minOccurs="0" />
|
||||
<xs:any minOccurs="0" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="attribute-overrides">
|
||||
<xs:sequence>
|
||||
<xs:element name="attribute-override" type="orm:attribute-override" minOccurs="1" maxOccurs="unbounded" />
|
||||
<xs:any minOccurs="1" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="attribute-override">
|
||||
<xs:sequence>
|
||||
<xs:element name="field" type="orm:field" minOccurs="1" />
|
||||
<xs:any minOccurs="1" maxOccurs="unbounded" namespace="##other"/>
|
||||
</xs:sequence>
|
||||
<xs:attribute name="name" type="xs:NMTOKEN" use="required" />
|
||||
</xs:complexType>
|
||||
|
||||
</xs:schema>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?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
|
||||
@@ -15,22 +13,25 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
use Doctrine\DBAL\Types\Type,
|
||||
Doctrine\ORM\Query\QueryException;
|
||||
use Doctrine\Common\Util\ClassUtils;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
|
||||
use Doctrine\DBAL\Types\Type;
|
||||
use Doctrine\DBAL\Cache\QueryCacheProfile;
|
||||
|
||||
use Doctrine\ORM\Query\QueryException;
|
||||
|
||||
/**
|
||||
* Base contract for ORM queries. Base class for Query and NativeQuery.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
@@ -58,14 +59,14 @@ abstract class AbstractQuery
|
||||
const HYDRATE_SINGLE_SCALAR = 4;
|
||||
|
||||
/**
|
||||
* @var array The parameter map of this query.
|
||||
* Very simple object hydrator (optimized for performance).
|
||||
*/
|
||||
protected $_params = array();
|
||||
const HYDRATE_SIMPLEOBJECT = 5;
|
||||
|
||||
/**
|
||||
* @var array The parameter type map of this query.
|
||||
* @var \Doctrine\Common\Collections\ArrayCollection The parameter map of this query.
|
||||
*/
|
||||
protected $_paramTypes = array();
|
||||
protected $parameters;
|
||||
|
||||
/**
|
||||
* @var ResultSetMapping The user-specified ResultSetMapping to use.
|
||||
@@ -73,7 +74,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;
|
||||
|
||||
@@ -88,23 +89,9 @@ abstract class AbstractQuery
|
||||
protected $_hydrationMode = self::HYDRATE_OBJECT;
|
||||
|
||||
/**
|
||||
* The locally set cache driver used for caching result sets of this query.
|
||||
*
|
||||
* @var CacheDriver
|
||||
* @param \Doctrine\DBAL\Cache\QueryCacheProfile
|
||||
*/
|
||||
protected $_resultCacheDriver;
|
||||
|
||||
/**
|
||||
* Boolean flag for whether or not to cache the results of this query.
|
||||
*
|
||||
* @var boolean
|
||||
*/
|
||||
protected $_useResultCache;
|
||||
|
||||
/**
|
||||
* @var string The id to store the result cache entry under.
|
||||
*/
|
||||
protected $_resultCacheId;
|
||||
protected $_queryCacheProfile;
|
||||
|
||||
/**
|
||||
* @var boolean Boolean value that indicates whether or not expire the result cache.
|
||||
@@ -112,24 +99,34 @@ abstract class AbstractQuery
|
||||
protected $_expireResultCache = false;
|
||||
|
||||
/**
|
||||
* @var int Result Cache lifetime.
|
||||
* @param \Doctrine\DBAL\Cache\QueryCacheProfile
|
||||
*/
|
||||
protected $_resultCacheTTL;
|
||||
protected $_hydrationCacheProfile;
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
$this->_em = $em;
|
||||
$this->parameters = new ArrayCollection();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SQL query that corresponds to this query object.
|
||||
* The returned SQL syntax depends on the connection driver that is used
|
||||
* by this query object at the time of this method call.
|
||||
*
|
||||
* @return string SQL query
|
||||
*/
|
||||
abstract public function getSQL();
|
||||
|
||||
/**
|
||||
* Retrieves the associated EntityManager of this Query instance.
|
||||
*
|
||||
* @return Doctrine\ORM\EntityManager
|
||||
* @return \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
public function getEntityManager()
|
||||
{
|
||||
@@ -145,40 +142,67 @@ abstract class AbstractQuery
|
||||
*/
|
||||
public function free()
|
||||
{
|
||||
$this->_params = array();
|
||||
$this->_paramTypes = array();
|
||||
$this->parameters = new ArrayCollection();
|
||||
|
||||
$this->_hints = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all defined parameters.
|
||||
*
|
||||
* @return array The defined query parameters.
|
||||
* @return \Doctrine\Common\Collections\ArrayCollection The defined query parameters.
|
||||
*/
|
||||
public function getParameters()
|
||||
{
|
||||
return $this->_params;
|
||||
return $this->parameters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a query parameter.
|
||||
*
|
||||
* @param mixed $key The key (index or name) of the bound parameter.
|
||||
*
|
||||
* @return mixed The value of the bound parameter.
|
||||
*/
|
||||
public function getParameter($key)
|
||||
{
|
||||
return isset($this->_params[$key]) ? $this->_params[$key] : null;
|
||||
$filteredParameters = $this->parameters->filter(
|
||||
function ($parameter) use ($key)
|
||||
{
|
||||
// Must not be identical because of string to integer conversion
|
||||
return ($key == $parameter->getName());
|
||||
}
|
||||
);
|
||||
|
||||
return count($filteredParameters) ? $filteredParameters->first() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the SQL query that corresponds to this query object.
|
||||
* The returned SQL syntax depends on the connection driver that is used
|
||||
* by this query object at the time of this method call.
|
||||
* Sets a collection of query parameters.
|
||||
*
|
||||
* @return string SQL query
|
||||
* @param \Doctrine\Common\Collections\ArrayCollection|array $parameters
|
||||
*
|
||||
* @return \Doctrine\ORM\AbstractQuery This query instance.
|
||||
*/
|
||||
abstract public function getSQL();
|
||||
public function setParameters($parameters)
|
||||
{
|
||||
// BC compatibility with 2.3-
|
||||
if (is_array($parameters)) {
|
||||
$parameterCollection = new ArrayCollection();
|
||||
|
||||
foreach ($parameters as $key => $value) {
|
||||
$parameter = new Query\Parameter($key, $value);
|
||||
|
||||
$parameterCollection->add($parameter);
|
||||
}
|
||||
|
||||
$parameters = $parameterCollection;
|
||||
}
|
||||
|
||||
$this->parameters = $parameters;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a query parameter.
|
||||
@@ -188,78 +212,191 @@ 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) {
|
||||
$this->_paramTypes[$key] = $type;
|
||||
$filteredParameters = $this->parameters->filter(
|
||||
function ($parameter) use ($key)
|
||||
{
|
||||
// Must not be identical because of string to integer conversion
|
||||
return ($key == $parameter->getName());
|
||||
}
|
||||
);
|
||||
|
||||
if (count($filteredParameters)) {
|
||||
$parameter = $filteredParameters->first();
|
||||
$parameter->setValue($value, $type);
|
||||
|
||||
return $this;
|
||||
}
|
||||
$this->_params[$key] = $value;
|
||||
|
||||
$parameter = new Query\Parameter($key, $value, $type);
|
||||
|
||||
$this->parameters->add($parameter);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a collection of query parameters.
|
||||
* Process an individual parameter value
|
||||
*
|
||||
* @param array $params
|
||||
* @param array $types
|
||||
* @return Doctrine\ORM\AbstractQuery This query instance.
|
||||
* @param mixed $value
|
||||
* @return array
|
||||
*/
|
||||
public function setParameters(array $params, array $types = array())
|
||||
public function processParameterValue($value)
|
||||
{
|
||||
foreach ($params as $key => $value) {
|
||||
if (isset($types[$key])) {
|
||||
$this->setParameter($key, $value, $types[$key]);
|
||||
} else {
|
||||
$this->setParameter($key, $value);
|
||||
}
|
||||
switch (true) {
|
||||
case is_array($value):
|
||||
foreach ($value as $key => $paramValue) {
|
||||
$paramValue = $this->processParameterValue($paramValue);
|
||||
$value[$key] = is_array($paramValue) ? $paramValue[key($paramValue)] : $paramValue;
|
||||
}
|
||||
|
||||
return $value;
|
||||
|
||||
case is_object($value) && $this->_em->getMetadataFactory()->hasMetadataFor(ClassUtils::getClass($value)):
|
||||
return $this->convertObjectParameterToScalarValue($value);
|
||||
|
||||
default:
|
||||
return $value;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
private function convertObjectParameterToScalarValue($value)
|
||||
{
|
||||
$class = $this->_em->getClassMetadata(get_class($value));
|
||||
|
||||
if ($class->isIdentifierComposite) {
|
||||
throw new \InvalidArgumentException(
|
||||
"Binding an entity with a composite primary key to a query is not supported. " .
|
||||
"You should split the parameter into the explicit fields and bind them seperately."
|
||||
);
|
||||
}
|
||||
|
||||
$values = ($this->_em->getUnitOfWork()->getEntityState($value) === UnitOfWork::STATE_MANAGED)
|
||||
? $this->_em->getUnitOfWork()->getEntityIdentifier($value)
|
||||
: $class->getIdentifierValues($value);
|
||||
|
||||
$value = $values[$class->getSingleIdentifierFieldName()];
|
||||
|
||||
if ( ! $value) {
|
||||
throw new \InvalidArgumentException(
|
||||
"Binding entities to query parameters only allowed for entities that have an identifier."
|
||||
);
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
$this->_resultSetMapping = $rsm;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a cache driver to be used for caching result sets.
|
||||
* Set a cache profile for hydration caching.
|
||||
*
|
||||
* @param Doctrine\Common\Cache\Cache $driver Cache driver
|
||||
* @return Doctrine\ORM\AbstractQuery
|
||||
* If no result cache driver is set in the QueryCacheProfile, the default
|
||||
* result cache driver is used from the configuration.
|
||||
*
|
||||
* Important: Hydration caching does NOT register entities in the
|
||||
* UnitOfWork when retrieved from the cache. Never use result cached
|
||||
* entities for requests that also flush the EntityManager. If you want
|
||||
* some form of caching with UnitOfWork registration you should use
|
||||
* {@see AbstractQuery::setResultCacheProfile()}.
|
||||
*
|
||||
* @example
|
||||
* $lifetime = 100;
|
||||
* $resultKey = "abc";
|
||||
* $query->setHydrationCacheProfile(new QueryCacheProfile());
|
||||
* $query->setHydrationCacheProfile(new QueryCacheProfile($lifetime, $resultKey));
|
||||
*
|
||||
* @param \Doctrine\DBAL\Cache\QueryCacheProfile $profile
|
||||
* @return \Doctrine\ORM\AbstractQuery
|
||||
*/
|
||||
public function setHydrationCacheProfile(QueryCacheProfile $profile = null)
|
||||
{
|
||||
if ( ! $profile->getResultCacheDriver()) {
|
||||
$resultCacheDriver = $this->_em->getConfiguration()->getHydrationCacheImpl();
|
||||
$profile = $profile->setResultCacheDriver($resultCacheDriver);
|
||||
}
|
||||
|
||||
$this->_hydrationCacheProfile = $profile;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Doctrine\DBAL\Cache\QueryCacheProfile
|
||||
*/
|
||||
public function getHydrationCacheProfile()
|
||||
{
|
||||
return $this->_hydrationCacheProfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a cache profile for the result cache.
|
||||
*
|
||||
* If no result cache driver is set in the QueryCacheProfile, the default
|
||||
* result cache driver is used from the configuration.
|
||||
*
|
||||
* @param \Doctrine\DBAL\Cache\QueryCacheProfile $profile
|
||||
* @return \Doctrine\ORM\AbstractQuery
|
||||
*/
|
||||
public function setResultCacheProfile(QueryCacheProfile $profile = null)
|
||||
{
|
||||
if ( ! $profile->getResultCacheDriver()) {
|
||||
$resultCacheDriver = $this->_em->getConfiguration()->getResultCacheImpl();
|
||||
$profile = $profile->setResultCacheDriver($resultCacheDriver);
|
||||
}
|
||||
|
||||
$this->_queryCacheProfile = $profile;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a cache driver to be used for caching result sets and implictly enables caching.
|
||||
*
|
||||
* @param \Doctrine\Common\Cache\Cache $driver Cache driver
|
||||
* @return \Doctrine\ORM\AbstractQuery
|
||||
*/
|
||||
public function setResultCacheDriver($resultCacheDriver = null)
|
||||
{
|
||||
if ($resultCacheDriver !== null && ! ($resultCacheDriver instanceof \Doctrine\Common\Cache\Cache)) {
|
||||
throw ORMException::invalidResultCacheDriver();
|
||||
}
|
||||
$this->_resultCacheDriver = $resultCacheDriver;
|
||||
if ($resultCacheDriver) {
|
||||
$this->_useResultCache = true;
|
||||
}
|
||||
|
||||
$this->_queryCacheProfile = $this->_queryCacheProfile
|
||||
? $this->_queryCacheProfile->setResultCacheDriver($resultCacheDriver)
|
||||
: new QueryCacheProfile(0, null, $resultCacheDriver);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the cache driver used for caching result sets.
|
||||
*
|
||||
* @return Doctrine\Common\Cache\Cache Cache driver
|
||||
* @deprecated
|
||||
* @return \Doctrine\Common\Cache\Cache Cache driver
|
||||
*/
|
||||
public function getResultCacheDriver()
|
||||
{
|
||||
if ($this->_resultCacheDriver) {
|
||||
return $this->_resultCacheDriver;
|
||||
} else {
|
||||
return $this->_em->getConfiguration()->getResultCacheImpl();
|
||||
if ($this->_queryCacheProfile && $this->_queryCacheProfile->getResultCacheDriver()) {
|
||||
return $this->_queryCacheProfile->getResultCacheDriver();
|
||||
}
|
||||
|
||||
return $this->_em->getConfiguration()->getResultCacheImpl();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -267,57 +404,62 @@ abstract class AbstractQuery
|
||||
* how long and which ID to use for the cache entry.
|
||||
*
|
||||
* @param boolean $bool
|
||||
* @param integer $timeToLive
|
||||
* @param integer $lifetime
|
||||
* @param string $resultCacheId
|
||||
* @return This query instance.
|
||||
* @return \Doctrine\ORM\AbstractQuery This query instance.
|
||||
*/
|
||||
public function useResultCache($bool, $timeToLive = null, $resultCacheId = null)
|
||||
public function useResultCache($bool, $lifetime = null, $resultCacheId = null)
|
||||
{
|
||||
$this->_useResultCache = $bool;
|
||||
if ($timeToLive) {
|
||||
$this->setResultCacheLifetime($timeToLive);
|
||||
}
|
||||
if ($resultCacheId) {
|
||||
$this->_resultCacheId = $resultCacheId;
|
||||
if ($bool) {
|
||||
$this->setResultCacheLifetime($lifetime);
|
||||
$this->setResultCacheId($resultCacheId);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->_queryCacheProfile = null;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* @param integer $lifetime How long the cache entry is valid.
|
||||
* @return \Doctrine\ORM\AbstractQuery This query instance.
|
||||
*/
|
||||
public function setResultCacheLifetime($timeToLive)
|
||||
public function setResultCacheLifetime($lifetime)
|
||||
{
|
||||
if ($timeToLive !== null) {
|
||||
$timeToLive = (int) $timeToLive;
|
||||
}
|
||||
$lifetime = ($lifetime !== null) ? (int) $lifetime : 0;
|
||||
|
||||
$this->_queryCacheProfile = $this->_queryCacheProfile
|
||||
? $this->_queryCacheProfile->setLifetime($lifetime)
|
||||
: new QueryCacheProfile($lifetime, null, $this->_em->getConfiguration()->getResultCacheImpl());
|
||||
|
||||
$this->_resultCacheTTL = $timeToLive;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the lifetime of resultset cache.
|
||||
*
|
||||
* @deprecated
|
||||
* @return integer
|
||||
*/
|
||||
public function getResultCacheLifetime()
|
||||
{
|
||||
return $this->_resultCacheTTL;
|
||||
return $this->_queryCacheProfile ? $this->_queryCacheProfile->getLifetime() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines if the result cache is active or not.
|
||||
*
|
||||
* @param boolean $expire Whether or not to force resultset cache expiration.
|
||||
* @return Doctrine\ORM\AbstractQuery This query instance.
|
||||
* @return \Doctrine\ORM\AbstractQuery This query instance.
|
||||
*/
|
||||
public function expireResultCache($expire = true)
|
||||
{
|
||||
$this->_expireResultCache = $expire;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -331,16 +473,46 @@ abstract class AbstractQuery
|
||||
return $this->_expireResultCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return QueryCacheProfile
|
||||
*/
|
||||
public function getQueryCacheProfile()
|
||||
{
|
||||
return $this->_queryCacheProfile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the default fetch mode of an association for this query.
|
||||
*
|
||||
* $fetchMode can be one of ClassMetadata::FETCH_EAGER or ClassMetadata::FETCH_LAZY
|
||||
*
|
||||
* @param string $class
|
||||
* @param string $assocName
|
||||
* @param int $fetchMode
|
||||
* @return 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)
|
||||
{
|
||||
$this->_hydrationMode = $hydrationMode;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -357,37 +529,63 @@ abstract class AbstractQuery
|
||||
/**
|
||||
* Gets the list of results for the query.
|
||||
*
|
||||
* Alias for execute(array(), $hydrationMode = HYDRATE_OBJECT).
|
||||
* Alias for execute(null, $hydrationMode = HYDRATE_OBJECT).
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getResult($hydrationMode = self::HYDRATE_OBJECT)
|
||||
{
|
||||
return $this->execute(array(), $hydrationMode);
|
||||
return $this->execute(null, $hydrationMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the array of results for the query.
|
||||
*
|
||||
* Alias for execute(array(), HYDRATE_ARRAY).
|
||||
* Alias for execute(null, HYDRATE_ARRAY).
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getArrayResult()
|
||||
{
|
||||
return $this->execute(array(), self::HYDRATE_ARRAY);
|
||||
return $this->execute(null, self::HYDRATE_ARRAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the scalar results for the query.
|
||||
*
|
||||
* Alias for execute(array(), HYDRATE_SCALAR).
|
||||
* Alias for execute(null, HYDRATE_SCALAR).
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getScalarResult()
|
||||
{
|
||||
return $this->execute(array(), self::HYDRATE_SCALAR);
|
||||
return $this->execute(null, self::HYDRATE_SCALAR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get exactly one result or null.
|
||||
*
|
||||
* @throws NonUniqueResultException
|
||||
* @param int $hydrationMode
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOneOrNullResult($hydrationMode = null)
|
||||
{
|
||||
$result = $this->execute(null, $hydrationMode);
|
||||
|
||||
if ($this->_hydrationMode !== self::HYDRATE_SINGLE_SCALAR && ! $result) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ( ! is_array($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
if (count($result) > 1) {
|
||||
throw new NonUniqueResultException;
|
||||
}
|
||||
|
||||
return array_shift($result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -405,20 +603,21 @@ abstract class AbstractQuery
|
||||
*/
|
||||
public function getSingleResult($hydrationMode = null)
|
||||
{
|
||||
$result = $this->execute(array(), $hydrationMode);
|
||||
$result = $this->execute(null, $hydrationMode);
|
||||
|
||||
if ($this->_hydrationMode !== self::HYDRATE_SINGLE_SCALAR && ! $result) {
|
||||
throw new NoResultException;
|
||||
}
|
||||
|
||||
if (is_array($result)) {
|
||||
if (count($result) > 1) {
|
||||
throw new NonUniqueResultException;
|
||||
}
|
||||
return array_shift($result);
|
||||
if ( ! is_array($result)) {
|
||||
return $result;
|
||||
}
|
||||
|
||||
return $result;
|
||||
if (count($result) > 1) {
|
||||
throw new NonUniqueResultException;
|
||||
}
|
||||
|
||||
return array_shift($result);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -439,11 +638,12 @@ 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)
|
||||
{
|
||||
$this->_hints[$name] = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
@@ -460,7 +660,7 @@ abstract class AbstractQuery
|
||||
|
||||
/**
|
||||
* Return the key value map of query hints that are currently set.
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getHints()
|
||||
@@ -472,83 +672,83 @@ abstract class AbstractQuery
|
||||
* Executes the query and returns an IterableResult that can be used to incrementally
|
||||
* iterate over the result.
|
||||
*
|
||||
* @param array $params The query parameters.
|
||||
* @param \Doctrine\Common\Collections\ArrayCollection|array $parameters The query parameters.
|
||||
* @param integer $hydrationMode The hydration mode to use.
|
||||
* @return IterableResult
|
||||
* @return \Doctrine\ORM\Internal\Hydration\IterableResult
|
||||
*/
|
||||
public function iterate(array $params = array(), $hydrationMode = self::HYDRATE_OBJECT)
|
||||
public function iterate($parameters = null, $hydrationMode = null)
|
||||
{
|
||||
if ($hydrationMode !== null) {
|
||||
$this->setHydrationMode($hydrationMode);
|
||||
}
|
||||
|
||||
if ( ! empty($parameters)) {
|
||||
$this->setParameters($parameters);
|
||||
}
|
||||
|
||||
$stmt = $this->_doExecute();
|
||||
|
||||
return $this->_em->newHydrator($this->_hydrationMode)->iterate(
|
||||
$this->_doExecute($params, $hydrationMode), $this->_resultSetMapping, $this->_hints
|
||||
$stmt, $this->_resultSetMapping, $this->_hints
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the query.
|
||||
*
|
||||
* @param array $params Any additional query parameters.
|
||||
* @param \Doctrine\Common\Collections\ArrayCollection|array $parameters Query parameters.
|
||||
* @param integer $hydrationMode Processing mode to be used during the hydration process.
|
||||
* @return mixed
|
||||
*/
|
||||
public function execute($params = array(), $hydrationMode = null)
|
||||
public function execute($parameters = null, $hydrationMode = null)
|
||||
{
|
||||
if ($hydrationMode !== null) {
|
||||
$this->setHydrationMode($hydrationMode);
|
||||
}
|
||||
|
||||
if ($params) {
|
||||
$this->setParameters($params);
|
||||
if ( ! empty($parameters)) {
|
||||
$this->setParameters($parameters);
|
||||
}
|
||||
|
||||
if (isset($this->_params[0])) {
|
||||
throw QueryException::invalidParameterPosition(0);
|
||||
}
|
||||
$setCacheEntry = function() {};
|
||||
|
||||
// Check result cache
|
||||
if ($this->_useResultCache && $cacheDriver = $this->getResultCacheDriver()) {
|
||||
list($key, $hash) = $this->getResultCacheId();
|
||||
$cached = $this->_expireResultCache ? false : $cacheDriver->fetch($hash);
|
||||
if ($this->_hydrationCacheProfile !== null) {
|
||||
list($cacheKey, $realCacheKey) = $this->getHydrationCacheId();
|
||||
|
||||
if ($cached === false || !isset($cached[$key])) {
|
||||
// Cache miss.
|
||||
$stmt = $this->_doExecute();
|
||||
$queryCacheProfile = $this->getHydrationCacheProfile();
|
||||
$cache = $queryCacheProfile->getResultCacheDriver();
|
||||
$result = $cache->fetch($cacheKey);
|
||||
|
||||
$result = $this->_em->getHydrator($this->_hydrationMode)->hydrateAll(
|
||||
$stmt, $this->_resultSetMapping, $this->_hints
|
||||
);
|
||||
|
||||
$cacheDriver->save($hash, array($key => $result), $this->_resultCacheTTL);
|
||||
|
||||
return $result;
|
||||
} else {
|
||||
// Cache hit.
|
||||
return $cached[$key];
|
||||
if (isset($result[$realCacheKey])) {
|
||||
return $result[$realCacheKey];
|
||||
}
|
||||
|
||||
if ( ! $result) {
|
||||
$result = array();
|
||||
}
|
||||
|
||||
$setCacheEntry = function($data) use ($cache, $result, $cacheKey, $realCacheKey, $queryCacheProfile) {
|
||||
$result[$realCacheKey] = $data;
|
||||
|
||||
$cache->save($cacheKey, $result, $queryCacheProfile->getLifetime());
|
||||
};
|
||||
}
|
||||
|
||||
$stmt = $this->_doExecute();
|
||||
|
||||
if (is_numeric($stmt)) {
|
||||
$setCacheEntry($stmt);
|
||||
|
||||
return $stmt;
|
||||
}
|
||||
|
||||
return $this->_em->getHydrator($this->_hydrationMode)->hydrateAll(
|
||||
$stmt, $this->_resultSetMapping, $this->_hints
|
||||
);
|
||||
}
|
||||
$data = $this->_em->getHydrator($this->_hydrationMode)->hydrateAll(
|
||||
$stmt, $this->_resultSetMapping, $this->_hints
|
||||
);
|
||||
|
||||
/**
|
||||
* Set the result cache id to use to store the result set cache entry.
|
||||
* If this is not explicitely set by the developer then a hash is automatically
|
||||
* generated for you.
|
||||
*
|
||||
* @param string $id
|
||||
* @return Doctrine\ORM\AbstractQuery This query instance.
|
||||
*/
|
||||
public function setResultCacheId($id)
|
||||
{
|
||||
$this->_resultCacheId = $id;
|
||||
return $this;
|
||||
$setCacheEntry($data);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -558,38 +758,56 @@ abstract class AbstractQuery
|
||||
*
|
||||
* @return array ($key, $hash)
|
||||
*/
|
||||
protected function getResultCacheId()
|
||||
protected function getHydrationCacheId()
|
||||
{
|
||||
if ($this->_resultCacheId) {
|
||||
return array($this->_resultCacheId, $this->_resultCacheId);
|
||||
} else {
|
||||
$params = $this->_params;
|
||||
foreach ($params AS $key => $value) {
|
||||
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);
|
||||
}
|
||||
$params[$key] = $idValues;
|
||||
} else {
|
||||
$params[$key] = $value;
|
||||
}
|
||||
}
|
||||
$parameters = array();
|
||||
|
||||
$sql = $this->getSql();
|
||||
ksort($this->_hints);
|
||||
$key = implode(";", (array)$sql) . var_export($params, true) .
|
||||
var_export($this->_hints, true)."&hydrationMode=".$this->_hydrationMode;
|
||||
return array($key, md5($key));
|
||||
foreach ($this->getParameters() as $parameter) {
|
||||
$parameters[$parameter->getName()] = $this->processParameterValue($parameter->getValue());
|
||||
}
|
||||
|
||||
$sql = $this->getSQL();
|
||||
$queryCacheProfile = $this->getHydrationCacheProfile();
|
||||
$hints = $this->getHints();
|
||||
$hints['hydrationMode'] = $this->getHydrationMode();
|
||||
|
||||
ksort($hints);
|
||||
|
||||
return $queryCacheProfile->generateCacheKeys($sql, $parameters, $hints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the result cache id to use to store the result set cache entry.
|
||||
* If this is not explicitly set by the developer then a hash is automatically
|
||||
* generated for you.
|
||||
*
|
||||
* @param string $id
|
||||
* @return \Doctrine\ORM\AbstractQuery This query instance.
|
||||
*/
|
||||
public function setResultCacheId($id)
|
||||
{
|
||||
$this->_queryCacheProfile = $this->_queryCacheProfile
|
||||
? $this->_queryCacheProfile->setCacheKey($id)
|
||||
: new QueryCacheProfile(0, $id, $this->_em->getConfiguration()->getResultCacheImpl());
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the result cache id to use to store the result set cache entry if set.
|
||||
*
|
||||
* @deprecated
|
||||
* @return string
|
||||
*/
|
||||
public function getResultCacheId()
|
||||
{
|
||||
return $this->_queryCacheProfile ? $this->_queryCacheProfile->getCacheKey() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the query and returns a the resulting Statement object.
|
||||
*
|
||||
* @return Doctrine\DBAL\Driver\Statement The executed database statement that holds the results.
|
||||
* @return \Doctrine\DBAL\Driver\Statement The executed database statement that holds the results.
|
||||
*/
|
||||
abstract protected function _doExecute();
|
||||
|
||||
@@ -600,8 +818,8 @@ abstract class AbstractQuery
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$this->_params = array();
|
||||
$this->_paramTypes = array();
|
||||
$this->parameters = new ArrayCollection();
|
||||
|
||||
$this->_hints = array();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,14 +13,24 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
use Doctrine\Common\Cache\Cache,
|
||||
Doctrine\ORM\Mapping\Driver\Driver;
|
||||
Doctrine\Common\Cache\ArrayCache,
|
||||
Doctrine\Common\Annotations\AnnotationRegistry,
|
||||
Doctrine\Common\Annotations\AnnotationReader,
|
||||
Doctrine\Common\Persistence\Mapping\Driver\MappingDriver,
|
||||
Doctrine\ORM\Mapping\Driver\AnnotationDriver,
|
||||
Doctrine\ORM\Mapping\QuoteStrategy,
|
||||
Doctrine\ORM\Mapping\DefaultQuoteStrategy,
|
||||
Doctrine\ORM\Mapping\NamingStrategy,
|
||||
Doctrine\ORM\Mapping\DefaultNamingStrategy,
|
||||
Doctrine\Common\Annotations\SimpleAnnotationReader,
|
||||
Doctrine\Common\Annotations\CachedReader;
|
||||
|
||||
/**
|
||||
* Configuration container for all configuration options of Doctrine.
|
||||
@@ -52,8 +62,9 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
*/
|
||||
public function getProxyDir()
|
||||
{
|
||||
return isset($this->_attributes['proxyDir']) ?
|
||||
$this->_attributes['proxyDir'] : null;
|
||||
return isset($this->_attributes['proxyDir'])
|
||||
? $this->_attributes['proxyDir']
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -64,8 +75,9 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
*/
|
||||
public function getAutoGenerateProxyClasses()
|
||||
{
|
||||
return isset($this->_attributes['autoGenerateProxyClasses']) ?
|
||||
$this->_attributes['autoGenerateProxyClasses'] : true;
|
||||
return isset($this->_attributes['autoGenerateProxyClasses'])
|
||||
? $this->_attributes['autoGenerateProxyClasses']
|
||||
: true;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,18 +93,19 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
|
||||
/**
|
||||
* Gets the namespace where proxy classes reside.
|
||||
*
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getProxyNamespace()
|
||||
{
|
||||
return isset($this->_attributes['proxyNamespace']) ?
|
||||
$this->_attributes['proxyNamespace'] : null;
|
||||
return isset($this->_attributes['proxyNamespace'])
|
||||
? $this->_attributes['proxyNamespace']
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the namespace where proxy classes reside.
|
||||
*
|
||||
*
|
||||
* @param string $ns
|
||||
*/
|
||||
public function setProxyNamespace($ns)
|
||||
@@ -103,27 +116,40 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
/**
|
||||
* Sets the cache driver implementation that is used for metadata caching.
|
||||
*
|
||||
* @param Driver $driverImpl
|
||||
* @param MappingDriver $driverImpl
|
||||
* @todo Force parameter to be a Closure to ensure lazy evaluation
|
||||
* (as soon as a metadata cache is in effect, the driver never needs to initialize).
|
||||
*/
|
||||
public function setMetadataDriverImpl(Driver $driverImpl)
|
||||
public function setMetadataDriverImpl(MappingDriver $driverImpl)
|
||||
{
|
||||
$this->_attributes['metadataDriverImpl'] = $driverImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new default annotation driver with a correctly configured annotation reader.
|
||||
*
|
||||
* Add a new default annotation driver with a correctly configured annotation reader. If $useSimpleAnnotationReader
|
||||
* is true, the notation `@Entity` will work, otherwise, the notation `@ORM\Entity` will be supported.
|
||||
*
|
||||
* @param array $paths
|
||||
* @return Mapping\Driver\AnnotationDriver
|
||||
* @param bool $useSimpleAnnotationReader
|
||||
* @return AnnotationDriver
|
||||
*/
|
||||
public function newDefaultAnnotationDriver($paths = array())
|
||||
public function newDefaultAnnotationDriver($paths = array(), $useSimpleAnnotationReader = true)
|
||||
{
|
||||
$reader = new \Doctrine\Common\Annotations\AnnotationReader();
|
||||
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
|
||||
|
||||
return new \Doctrine\ORM\Mapping\Driver\AnnotationDriver($reader, (array)$paths);
|
||||
AnnotationRegistry::registerFile(__DIR__ . '/Mapping/Driver/DoctrineAnnotations.php');
|
||||
|
||||
if ($useSimpleAnnotationReader) {
|
||||
// Register the ORM Annotations in the AnnotationRegistry
|
||||
$reader = new SimpleAnnotationReader();
|
||||
$reader->addNamespace('Doctrine\ORM\Mapping');
|
||||
$cachedReader = new CachedReader($reader, new ArrayCache());
|
||||
|
||||
return new AnnotationDriver($cachedReader, (array) $paths);
|
||||
}
|
||||
|
||||
return new AnnotationDriver(
|
||||
new CachedReader(new AnnotationReader(), new ArrayCache()),
|
||||
(array) $paths
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,9 +166,9 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
/**
|
||||
* Resolves a registered namespace alias to the full namespace.
|
||||
*
|
||||
* @param string $entityNamespaceAlias
|
||||
* @param string $entityNamespaceAlias
|
||||
* @throws ORMException
|
||||
* @return string
|
||||
* @throws MappingException
|
||||
*/
|
||||
public function getEntityNamespace($entityNamespaceAlias)
|
||||
{
|
||||
@@ -156,45 +182,34 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
/**
|
||||
* Set the entity alias map
|
||||
*
|
||||
* @param array $entityAliasMap
|
||||
* @return void
|
||||
* @param array $entityNamespaces
|
||||
*/
|
||||
public function setEntityNamespaces(array $entityNamespaces)
|
||||
{
|
||||
$this->_attributes['entityNamespaces'] = $entityNamespaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of registered entity namespace aliases.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getEntityNamespaces()
|
||||
{
|
||||
return $this->_attributes['entityNamespaces'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cache driver implementation that is used for the mapping metadata.
|
||||
*
|
||||
* @throws ORMException
|
||||
* @return Mapping\Driver\Driver
|
||||
* @return MappingDriver
|
||||
*/
|
||||
public function getMetadataDriverImpl()
|
||||
{
|
||||
return isset($this->_attributes['metadataDriverImpl']) ?
|
||||
$this->_attributes['metadataDriverImpl'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cache driver implementation that is used for query result caching.
|
||||
*
|
||||
* @return \Doctrine\Common\Cache\Cache
|
||||
*/
|
||||
public function getResultCacheImpl()
|
||||
{
|
||||
return isset($this->_attributes['resultCacheImpl']) ?
|
||||
$this->_attributes['resultCacheImpl'] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache driver implementation that is used for query result caching.
|
||||
*
|
||||
* @param \Doctrine\Common\Cache\Cache $cacheImpl
|
||||
*/
|
||||
public function setResultCacheImpl(Cache $cacheImpl)
|
||||
{
|
||||
$this->_attributes['resultCacheImpl'] = $cacheImpl;
|
||||
return isset($this->_attributes['metadataDriverImpl'])
|
||||
? $this->_attributes['metadataDriverImpl']
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -204,8 +219,9 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
*/
|
||||
public function getQueryCacheImpl()
|
||||
{
|
||||
return isset($this->_attributes['queryCacheImpl']) ?
|
||||
$this->_attributes['queryCacheImpl'] : null;
|
||||
return isset($this->_attributes['queryCacheImpl'])
|
||||
? $this->_attributes['queryCacheImpl']
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -218,6 +234,28 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
$this->_attributes['queryCacheImpl'] = $cacheImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cache driver implementation that is used for the hydration cache (SQL cache).
|
||||
*
|
||||
* @return \Doctrine\Common\Cache\Cache
|
||||
*/
|
||||
public function getHydrationCacheImpl()
|
||||
{
|
||||
return isset($this->_attributes['hydrationCacheImpl'])
|
||||
? $this->_attributes['hydrationCacheImpl']
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache driver implementation that is used for the hydration cache (SQL cache).
|
||||
*
|
||||
* @param \Doctrine\Common\Cache\Cache $cacheImpl
|
||||
*/
|
||||
public function setHydrationCacheImpl(Cache $cacheImpl)
|
||||
{
|
||||
$this->_attributes['hydrationCacheImpl'] = $cacheImpl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cache driver implementation that is used for metadata caching.
|
||||
*
|
||||
@@ -225,8 +263,9 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
*/
|
||||
public function getMetadataCacheImpl()
|
||||
{
|
||||
return isset($this->_attributes['metadataCacheImpl']) ?
|
||||
$this->_attributes['metadataCacheImpl'] : null;
|
||||
return isset($this->_attributes['metadataCacheImpl'])
|
||||
? $this->_attributes['metadataCacheImpl']
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,6 +293,7 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
* Gets a previously registered named DQL query.
|
||||
*
|
||||
* @param string $name The name of the query.
|
||||
* @throws ORMException
|
||||
* @return string The DQL query.
|
||||
*/
|
||||
public function getNamedQuery($name)
|
||||
@@ -261,15 +301,16 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
if ( ! isset($this->_attributes['namedQueries'][$name])) {
|
||||
throw ORMException::namedQueryNotFound($name);
|
||||
}
|
||||
|
||||
return $this->_attributes['namedQueries'][$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a named native query to the configuration.
|
||||
*
|
||||
* @param string $name The name of the query.
|
||||
* @param string $sql The native SQL query string.
|
||||
* @param ResultSetMapping $rsm The ResultSetMapping used for the results of the SQL query.
|
||||
* @param string $name The name of the query.
|
||||
* @param string $sql The native SQL query string.
|
||||
* @param Query\ResultSetMapping $rsm The ResultSetMapping used for the results of the SQL query.
|
||||
*/
|
||||
public function addNamedNativeQuery($name, $sql, Query\ResultSetMapping $rsm)
|
||||
{
|
||||
@@ -279,15 +320,17 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
/**
|
||||
* Gets the components of a previously registered named native query.
|
||||
*
|
||||
* @param string $name The name of the query.
|
||||
* @return array A tuple with the first element being the SQL string and the second
|
||||
* element being the ResultSetMapping.
|
||||
* @param string $name The name of the query.
|
||||
* @throws ORMException
|
||||
* @return array A tuple with the first element being the SQL string and the second
|
||||
* element being the ResultSetMapping.
|
||||
*/
|
||||
public function getNamedNativeQuery($name)
|
||||
{
|
||||
if ( ! isset($this->_attributes['namedNativeQueries'][$name])) {
|
||||
throw ORMException::namedNativeQueryNotFound($name);
|
||||
}
|
||||
|
||||
return $this->_attributes['namedNativeQueries'][$name];
|
||||
}
|
||||
|
||||
@@ -300,12 +343,14 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
*/
|
||||
public function ensureProductionSettings()
|
||||
{
|
||||
if ( !$this->getQueryCacheImpl()) {
|
||||
if ( ! $this->getQueryCacheImpl()) {
|
||||
throw ORMException::queryCacheNotConfigured();
|
||||
}
|
||||
if ( !$this->getMetadataCacheImpl()) {
|
||||
|
||||
if ( ! $this->getMetadataCacheImpl()) {
|
||||
throw ORMException::metadataCacheNotConfigured();
|
||||
}
|
||||
|
||||
if ($this->getAutoGenerateProxyClasses()) {
|
||||
throw ORMException::proxyClassesAlwaysRegenerating();
|
||||
}
|
||||
@@ -320,23 +365,30 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $className
|
||||
* @throws ORMException
|
||||
*/
|
||||
public function addCustomStringFunction($name, $className)
|
||||
{
|
||||
if (Query\Parser::isInternalFunction($name)) {
|
||||
throw ORMException::overwriteInternalDQLFunctionNotAllowed($name);
|
||||
}
|
||||
|
||||
$this->_attributes['customStringFunctions'][strtolower($name)] = $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the implementation class name of a registered custom string DQL function.
|
||||
*
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function getCustomStringFunction($name)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
return isset($this->_attributes['customStringFunctions'][$name]) ?
|
||||
$this->_attributes['customStringFunctions'][$name] : null;
|
||||
|
||||
return isset($this->_attributes['customStringFunctions'][$name])
|
||||
? $this->_attributes['customStringFunctions'][$name]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -351,7 +403,9 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
*/
|
||||
public function setCustomStringFunctions(array $functions)
|
||||
{
|
||||
$this->_attributes['customStringFunctions'] = array_change_key_case($functions);
|
||||
foreach ($functions as $name => $className) {
|
||||
$this->addCustomStringFunction($name, $className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -363,23 +417,30 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $className
|
||||
* @throws ORMException
|
||||
*/
|
||||
public function addCustomNumericFunction($name, $className)
|
||||
{
|
||||
if (Query\Parser::isInternalFunction($name)) {
|
||||
throw ORMException::overwriteInternalDQLFunctionNotAllowed($name);
|
||||
}
|
||||
|
||||
$this->_attributes['customNumericFunctions'][strtolower($name)] = $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the implementation class name of a registered custom numeric DQL function.
|
||||
*
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function getCustomNumericFunction($name)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
return isset($this->_attributes['customNumericFunctions'][$name]) ?
|
||||
$this->_attributes['customNumericFunctions'][$name] : null;
|
||||
|
||||
return isset($this->_attributes['customNumericFunctions'][$name])
|
||||
? $this->_attributes['customNumericFunctions'][$name]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -394,7 +455,9 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
*/
|
||||
public function setCustomNumericFunctions(array $functions)
|
||||
{
|
||||
$this->_attributes['customNumericFunctions'] = array_change_key_case($functions);
|
||||
foreach ($functions as $name => $className) {
|
||||
$this->addCustomNumericFunction($name, $className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -406,23 +469,30 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $className
|
||||
* @throws ORMException
|
||||
*/
|
||||
public function addCustomDatetimeFunction($name, $className)
|
||||
{
|
||||
if (Query\Parser::isInternalFunction($name)) {
|
||||
throw ORMException::overwriteInternalDQLFunctionNotAllowed($name);
|
||||
}
|
||||
|
||||
$this->_attributes['customDatetimeFunctions'][strtolower($name)] = $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the implementation class name of a registered custom date/time DQL function.
|
||||
*
|
||||
*
|
||||
* @param string $name
|
||||
* @return string
|
||||
*/
|
||||
public function getCustomDatetimeFunction($name)
|
||||
{
|
||||
$name = strtolower($name);
|
||||
return isset($this->_attributes['customDatetimeFunctions'][$name]) ?
|
||||
$this->_attributes['customDatetimeFunctions'][$name] : null;
|
||||
|
||||
return isset($this->_attributes['customDatetimeFunctions'][$name])
|
||||
? $this->_attributes['customDatetimeFunctions'][$name]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -437,7 +507,23 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
*/
|
||||
public function setCustomDatetimeFunctions(array $functions)
|
||||
{
|
||||
$this->_attributes['customDatetimeFunctions'] = array_change_key_case($functions);
|
||||
foreach ($functions as $name => $className) {
|
||||
$this->addCustomDatetimeFunction($name, $className);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the custom hydrator modes in one pass.
|
||||
*
|
||||
* @param array An array of ($modeName => $hydrator)
|
||||
*/
|
||||
public function setCustomHydrationModes($modes)
|
||||
{
|
||||
$this->_attributes['customHydrationModes'] = array();
|
||||
|
||||
foreach ($modes as $modeName => $hydrator) {
|
||||
$this->addCustomHydrationMode($modeName, $hydrator);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -448,8 +534,9 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
*/
|
||||
public function getCustomHydrationMode($modeName)
|
||||
{
|
||||
return isset($this->_attributes['customHydrationModes'][$modeName]) ?
|
||||
$this->_attributes['customHydrationModes'][$modeName] : null;
|
||||
return isset($this->_attributes['customHydrationModes'][$modeName])
|
||||
? $this->_attributes['customHydrationModes'][$modeName]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -465,8 +552,8 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
|
||||
/**
|
||||
* Set a class metadata factory.
|
||||
*
|
||||
* @param string $cmf
|
||||
*
|
||||
* @param string $cmfName
|
||||
*/
|
||||
public function setClassMetadataFactoryName($cmfName)
|
||||
{
|
||||
@@ -478,9 +565,119 @@ class Configuration extends \Doctrine\DBAL\Configuration
|
||||
*/
|
||||
public function getClassMetadataFactoryName()
|
||||
{
|
||||
if (!isset($this->_attributes['classMetadataFactoryName'])) {
|
||||
if ( ! isset($this->_attributes['classMetadataFactoryName'])) {
|
||||
$this->_attributes['classMetadataFactoryName'] = 'Doctrine\ORM\Mapping\ClassMetadataFactory';
|
||||
}
|
||||
|
||||
return $this->_attributes['classMetadataFactoryName'];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a filter to the list of possible filters.
|
||||
*
|
||||
* @param string $name The name of the filter.
|
||||
* @param string $className The class name of the filter.
|
||||
*/
|
||||
public function addFilter($name, $className)
|
||||
{
|
||||
$this->_attributes['filters'][$name] = $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the class name for a given filter name.
|
||||
*
|
||||
* @param string $name The name of the filter.
|
||||
*
|
||||
* @return string The class name of the filter, or null of it is not
|
||||
* defined.
|
||||
*/
|
||||
public function getFilterClassName($name)
|
||||
{
|
||||
return isset($this->_attributes['filters'][$name])
|
||||
? $this->_attributes['filters'][$name]
|
||||
: null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set default repository class.
|
||||
*
|
||||
* @since 2.2
|
||||
* @param string $className
|
||||
* @throws ORMException If not is a \Doctrine\Common\Persistence\ObjectRepository
|
||||
*/
|
||||
public function setDefaultRepositoryClassName($className)
|
||||
{
|
||||
$reflectionClass = new \ReflectionClass($className);
|
||||
|
||||
if ( ! $reflectionClass->implementsInterface('Doctrine\Common\Persistence\ObjectRepository')) {
|
||||
throw ORMException::invalidEntityRepository($className);
|
||||
}
|
||||
|
||||
$this->_attributes['defaultRepositoryClassName'] = $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default repository class.
|
||||
*
|
||||
* @since 2.2
|
||||
* @return string
|
||||
*/
|
||||
public function getDefaultRepositoryClassName()
|
||||
{
|
||||
return isset($this->_attributes['defaultRepositoryClassName'])
|
||||
? $this->_attributes['defaultRepositoryClassName']
|
||||
: 'Doctrine\ORM\EntityRepository';
|
||||
}
|
||||
|
||||
/**
|
||||
* Set naming strategy.
|
||||
*
|
||||
* @since 2.3
|
||||
* @param NamingStrategy $namingStrategy
|
||||
*/
|
||||
public function setNamingStrategy(NamingStrategy $namingStrategy)
|
||||
{
|
||||
$this->_attributes['namingStrategy'] = $namingStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get naming strategy..
|
||||
*
|
||||
* @since 2.3
|
||||
* @return NamingStrategy
|
||||
*/
|
||||
public function getNamingStrategy()
|
||||
{
|
||||
if ( ! isset($this->_attributes['namingStrategy'])) {
|
||||
$this->_attributes['namingStrategy'] = new DefaultNamingStrategy();
|
||||
}
|
||||
|
||||
return $this->_attributes['namingStrategy'];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set quote strategy.
|
||||
*
|
||||
* @since 2.3
|
||||
* @param Doctrine\ORM\Mapping\QuoteStrategy $quoteStrategy
|
||||
*/
|
||||
public function setQuoteStrategy(QuoteStrategy $quoteStrategy)
|
||||
{
|
||||
$this->_attributes['quoteStrategy'] = $quoteStrategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get quote strategy.
|
||||
*
|
||||
* @since 2.3
|
||||
* @return Doctrine\ORM\Mapping\QuoteStrategy
|
||||
*/
|
||||
public function getQuoteStrategy()
|
||||
{
|
||||
if ( ! isset($this->_attributes['quoteStrategy'])) {
|
||||
$this->_attributes['quoteStrategy'] = new DefaultQuoteStrategy();
|
||||
}
|
||||
|
||||
return $this->_attributes['quoteStrategy'];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,20 +13,22 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
use Closure, Exception,
|
||||
use Exception,
|
||||
Doctrine\Common\EventManager,
|
||||
Doctrine\Common\Persistence\ObjectManager,
|
||||
Doctrine\DBAL\Connection,
|
||||
Doctrine\DBAL\LockMode,
|
||||
Doctrine\ORM\Mapping\ClassMetadata,
|
||||
Doctrine\ORM\Mapping\ClassMetadataFactory,
|
||||
Doctrine\ORM\Query\ResultSetMapping,
|
||||
Doctrine\ORM\Proxy\ProxyFactory;
|
||||
Doctrine\ORM\Proxy\ProxyFactory,
|
||||
Doctrine\ORM\Query\FilterCollection;
|
||||
|
||||
/**
|
||||
* The EntityManager is the central access point to ORM functionality.
|
||||
@@ -37,26 +39,26 @@ use Closure, Exception,
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class EntityManager
|
||||
class EntityManager implements ObjectManager
|
||||
{
|
||||
/**
|
||||
* 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;
|
||||
|
||||
@@ -70,14 +72,14 @@ class EntityManager
|
||||
/**
|
||||
* 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;
|
||||
|
||||
@@ -91,50 +93,64 @@ class EntityManager
|
||||
/**
|
||||
* The proxy factory used to create dynamic proxies.
|
||||
*
|
||||
* @var Doctrine\ORM\Proxy\ProxyFactory
|
||||
* @var \Doctrine\ORM\Proxy\ProxyFactory
|
||||
*/
|
||||
private $proxyFactory;
|
||||
|
||||
/**
|
||||
* @var ExpressionBuilder The expression builder instance used to generate query expressions.
|
||||
* The expression builder instance used to generate query expressions.
|
||||
*
|
||||
* @var \Doctrine\ORM\Query\Expr
|
||||
*/
|
||||
private $expressionBuilder;
|
||||
|
||||
/**
|
||||
* Whether the EntityManager is closed or not.
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $closed = false;
|
||||
|
||||
/**
|
||||
* Collection of query filters.
|
||||
*
|
||||
* @var Doctrine\ORM\Query\FilterCollection
|
||||
*/
|
||||
private $filterCollection;
|
||||
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
$this->conn = $conn;
|
||||
$this->config = $config;
|
||||
$this->conn = $conn;
|
||||
$this->config = $config;
|
||||
$this->eventManager = $eventManager;
|
||||
|
||||
$metadataFactoryClassName = $config->getClassMetadataFactoryName();
|
||||
|
||||
$this->metadataFactory = new $metadataFactoryClassName;
|
||||
$this->metadataFactory->setEntityManager($this);
|
||||
$this->metadataFactory->setCacheDriver($this->config->getMetadataCacheImpl());
|
||||
|
||||
$this->unitOfWork = new UnitOfWork($this);
|
||||
$this->proxyFactory = new ProxyFactory($this,
|
||||
$config->getProxyDir(),
|
||||
$config->getProxyNamespace(),
|
||||
$config->getAutoGenerateProxyClasses());
|
||||
|
||||
$this->unitOfWork = new UnitOfWork($this);
|
||||
$this->proxyFactory = new ProxyFactory(
|
||||
$this,
|
||||
$config->getProxyDir(),
|
||||
$config->getProxyNamespace(),
|
||||
$config->getAutoGenerateProxyClasses()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the database connection object used by the EntityManager.
|
||||
*
|
||||
* @return Doctrine\DBAL\Connection
|
||||
* @return \Doctrine\DBAL\Connection
|
||||
*/
|
||||
public function getConnection()
|
||||
{
|
||||
@@ -144,7 +160,7 @@ class EntityManager
|
||||
/**
|
||||
* Gets the metadata factory used to gather the metadata of classes.
|
||||
*
|
||||
* @return Doctrine\ORM\Mapping\ClassMetadataFactory
|
||||
* @return \Doctrine\ORM\Mapping\ClassMetadataFactory
|
||||
*/
|
||||
public function getMetadataFactory()
|
||||
{
|
||||
@@ -163,20 +179,19 @@ class EntityManager
|
||||
* ->where($expr->orX($expr->eq('u.id', 1), $expr->eq('u.id', 2)));
|
||||
* </code>
|
||||
*
|
||||
* @return ExpressionBuilder
|
||||
* @return \Doctrine\ORM\Query\Expr
|
||||
*/
|
||||
public function getExpressionBuilder()
|
||||
{
|
||||
if ($this->expressionBuilder === null) {
|
||||
$this->expressionBuilder = new Query\Expr;
|
||||
}
|
||||
|
||||
return $this->expressionBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a transaction on the underlying database connection.
|
||||
*
|
||||
* @deprecated Use {@link getConnection}.beginTransaction().
|
||||
*/
|
||||
public function beginTransaction()
|
||||
{
|
||||
@@ -193,26 +208,34 @@ class EntityManager
|
||||
* If an exception occurs during execution of the function or flushing or transaction commit,
|
||||
* the transaction is rolled back, the EntityManager closed and the exception re-thrown.
|
||||
*
|
||||
* @param Closure $func The function to execute transactionally.
|
||||
* @param callable $func The function to execute transactionally.
|
||||
* @return mixed Returns the non-empty value returned from the closure or true instead
|
||||
*/
|
||||
public function transactional(Closure $func)
|
||||
public function transactional($func)
|
||||
{
|
||||
if (!is_callable($func)) {
|
||||
throw new \InvalidArgumentException('Expected argument of type "callable", got "' . gettype($func) . '"');
|
||||
}
|
||||
|
||||
$this->conn->beginTransaction();
|
||||
|
||||
try {
|
||||
$func($this);
|
||||
$return = call_user_func($func, $this);
|
||||
|
||||
$this->flush();
|
||||
$this->conn->commit();
|
||||
|
||||
return $return ?: true;
|
||||
} catch (Exception $e) {
|
||||
$this->close();
|
||||
$this->conn->rollback();
|
||||
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Commits a transaction on the underlying database connection.
|
||||
*
|
||||
* @deprecated Use {@link getConnection}.commit().
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
@@ -221,8 +244,6 @@ class EntityManager
|
||||
|
||||
/**
|
||||
* Performs a rollback on the underlying database connection.
|
||||
*
|
||||
* @deprecated Use {@link getConnection}.rollback().
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
@@ -234,12 +255,12 @@ class EntityManager
|
||||
*
|
||||
* 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)
|
||||
@@ -250,15 +271,17 @@ class EntityManager
|
||||
/**
|
||||
* Creates a new Query object.
|
||||
*
|
||||
* @param string The DQL string.
|
||||
* @return Doctrine\ORM\Query
|
||||
* @param string $dql The DQL string.
|
||||
* @return \Doctrine\ORM\Query
|
||||
*/
|
||||
public function createQuery($dql = "")
|
||||
{
|
||||
$query = new Query($this);
|
||||
|
||||
if ( ! empty($dql)) {
|
||||
$query->setDql($dql);
|
||||
}
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
@@ -266,7 +289,7 @@ class EntityManager
|
||||
* Creates a Query from a named query.
|
||||
*
|
||||
* @param string $name
|
||||
* @return Doctrine\ORM\Query
|
||||
* @return \Doctrine\ORM\Query
|
||||
*/
|
||||
public function createNamedQuery($name)
|
||||
{
|
||||
@@ -283,8 +306,10 @@ class EntityManager
|
||||
public function createNativeQuery($sql, ResultSetMapping $rsm)
|
||||
{
|
||||
$query = new NativeQuery($this);
|
||||
|
||||
$query->setSql($sql);
|
||||
$query->setResultSetMapping($rsm);
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
@@ -292,11 +317,12 @@ class EntityManager
|
||||
* Creates a NativeQuery from a named native query.
|
||||
*
|
||||
* @param string $name
|
||||
* @return Doctrine\ORM\NativeQuery
|
||||
* @return \Doctrine\ORM\NativeQuery
|
||||
*/
|
||||
public function createNamedNativeQuery($name)
|
||||
{
|
||||
list($sql, $rsm) = $this->config->getNamedNativeQuery($name);
|
||||
|
||||
return $this->createNativeQuery($sql, $rsm);
|
||||
}
|
||||
|
||||
@@ -315,29 +341,95 @@ class EntityManager
|
||||
* 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
|
||||
* If an entity is explicitly passed to this method only this entity and
|
||||
* the cascade-persist semantics + scheduled inserts/removals are synchronized.
|
||||
*
|
||||
* @param object $entity
|
||||
* @throws \Doctrine\ORM\OptimisticLockException If a version check on an entity that
|
||||
* makes use of optimistic locking fails.
|
||||
*/
|
||||
public function flush()
|
||||
public function flush($entity = null)
|
||||
{
|
||||
$this->errorIfClosed();
|
||||
$this->unitOfWork->commit();
|
||||
}
|
||||
|
||||
$this->unitOfWork->commit($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds an Entity by its identifier.
|
||||
*
|
||||
* This is just a convenient shortcut for getRepository($entityName)->find($id).
|
||||
*
|
||||
* @param string $entityName
|
||||
* @param mixed $identifier
|
||||
* @param int $lockMode
|
||||
* @param int $lockVersion
|
||||
* @param mixed $id
|
||||
* @param integer $lockMode
|
||||
* @param integer $lockVersion
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function find($entityName, $identifier, $lockMode = LockMode::NONE, $lockVersion = null)
|
||||
public function find($entityName, $id, $lockMode = LockMode::NONE, $lockVersion = null)
|
||||
{
|
||||
return $this->getRepository($entityName)->find($identifier, $lockMode, $lockVersion);
|
||||
$class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
|
||||
|
||||
if ( ! is_array($id)) {
|
||||
$id = array($class->identifier[0] => $id);
|
||||
}
|
||||
|
||||
$sortedId = array();
|
||||
|
||||
foreach ($class->identifier as $identifier) {
|
||||
if ( ! isset($id[$identifier])) {
|
||||
throw ORMException::missingIdentifierField($class->name, $identifier);
|
||||
}
|
||||
|
||||
$sortedId[$identifier] = $id[$identifier];
|
||||
}
|
||||
|
||||
$unitOfWork = $this->getUnitOfWork();
|
||||
|
||||
// Check identity map first
|
||||
if (($entity = $unitOfWork->tryGetById($sortedId, $class->rootEntityName)) !== false) {
|
||||
if ( ! ($entity instanceof $class->name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
switch ($lockMode) {
|
||||
case LockMode::OPTIMISTIC:
|
||||
$this->lock($entity, $lockMode, $lockVersion);
|
||||
break;
|
||||
|
||||
case LockMode::PESSIMISTIC_READ:
|
||||
case LockMode::PESSIMISTIC_WRITE:
|
||||
$persister = $unitOfWork->getEntityPersister($class->name);
|
||||
$persister->refresh($sortedId, $entity, $lockMode);
|
||||
break;
|
||||
}
|
||||
|
||||
return $entity; // Hit!
|
||||
}
|
||||
|
||||
$persister = $unitOfWork->getEntityPersister($class->name);
|
||||
|
||||
switch ($lockMode) {
|
||||
case LockMode::NONE:
|
||||
return $persister->load($sortedId);
|
||||
|
||||
case LockMode::OPTIMISTIC:
|
||||
if ( ! $class->isVersioned) {
|
||||
throw OptimisticLockException::notVersioned($class->name);
|
||||
}
|
||||
|
||||
$entity = $persister->load($sortedId);
|
||||
|
||||
$unitOfWork->lock($entity, $lockMode, $lockVersion);
|
||||
|
||||
return $entity;
|
||||
|
||||
default:
|
||||
if ( ! $this->getConnection()->isTransactionActive()) {
|
||||
throw TransactionRequiredException::transactionRequired();
|
||||
}
|
||||
|
||||
return $persister->load($sortedId, null, null, array(), $lockMode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -345,27 +437,44 @@ class EntityManager
|
||||
* without actually loading it, if the entity is not yet loaded.
|
||||
*
|
||||
* @param string $entityName The name of the entity type.
|
||||
* @param mixed $identifier The entity identifier.
|
||||
* @param mixed $id The entity identifier.
|
||||
* @return object The entity reference.
|
||||
*/
|
||||
public function getReference($entityName, $identifier)
|
||||
public function getReference($entityName, $id)
|
||||
{
|
||||
$class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
|
||||
|
||||
if ( ! is_array($id)) {
|
||||
$id = array($class->identifier[0] => $id);
|
||||
}
|
||||
|
||||
$sortedId = array();
|
||||
|
||||
foreach ($class->identifier as $identifier) {
|
||||
if ( ! isset($id[$identifier])) {
|
||||
throw ORMException::missingIdentifierField($class->name, $identifier);
|
||||
}
|
||||
|
||||
$sortedId[$identifier] = $id[$identifier];
|
||||
}
|
||||
|
||||
// Check identity map first, if its already in there just return it.
|
||||
if ($entity = $this->unitOfWork->tryGetById($identifier, $class->rootEntityName)) {
|
||||
if (($entity = $this->unitOfWork->tryGetById($sortedId, $class->rootEntityName)) !== false) {
|
||||
return ($entity instanceof $class->name) ? $entity : null;
|
||||
}
|
||||
|
||||
if ($class->subClasses) {
|
||||
$entity = $this->find($entityName, $identifier);
|
||||
} else {
|
||||
if ( ! is_array($identifier)) {
|
||||
$identifier = array($class->identifier[0] => $identifier);
|
||||
}
|
||||
$entity = $this->proxyFactory->getProxy($class->name, $identifier);
|
||||
$this->unitOfWork->registerManaged($entity, $identifier, array());
|
||||
return $this->find($entityName, $sortedId);
|
||||
}
|
||||
|
||||
if ( ! is_array($sortedId)) {
|
||||
$sortedId = array($class->identifier[0] => $sortedId);
|
||||
}
|
||||
|
||||
$entity = $this->proxyFactory->getProxy($class->name, $sortedId);
|
||||
|
||||
$this->unitOfWork->registerManaged($entity, $sortedId, array());
|
||||
|
||||
return $entity;
|
||||
}
|
||||
|
||||
@@ -393,16 +502,20 @@ class EntityManager
|
||||
$class = $this->metadataFactory->getMetadataFor(ltrim($entityName, '\\'));
|
||||
|
||||
// Check identity map first, if its already in there just return it.
|
||||
if ($entity = $this->unitOfWork->tryGetById($identifier, $class->rootEntityName)) {
|
||||
if (($entity = $this->unitOfWork->tryGetById($identifier, $class->rootEntityName)) !== false) {
|
||||
return ($entity instanceof $class->name) ? $entity : null;
|
||||
}
|
||||
|
||||
if ( ! is_array($identifier)) {
|
||||
$identifier = array($class->identifier[0] => $identifier);
|
||||
}
|
||||
|
||||
$entity = $class->newInstance();
|
||||
|
||||
$class->setIdentifierValues($entity, $identifier);
|
||||
|
||||
$this->unitOfWork->registerManaged($entity, $identifier, array());
|
||||
$this->unitOfWork->markReadOnly($entity);
|
||||
|
||||
return $entity;
|
||||
}
|
||||
@@ -411,16 +524,11 @@ class EntityManager
|
||||
* Clears the EntityManager. All entities that are currently managed
|
||||
* by this EntityManager become detached.
|
||||
*
|
||||
* @param string $entityName
|
||||
* @param string $entityName if given, only entities of this type will get detached
|
||||
*/
|
||||
public function clear($entityName = null)
|
||||
{
|
||||
if ($entityName === null) {
|
||||
$this->unitOfWork->clear();
|
||||
} else {
|
||||
//TODO
|
||||
throw new ORMException("EntityManager#clear(\$entityName) not yet implemented.");
|
||||
}
|
||||
$this->unitOfWork->clear($entityName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -431,6 +539,7 @@ class EntityManager
|
||||
public function close()
|
||||
{
|
||||
$this->clear();
|
||||
|
||||
$this->closed = true;
|
||||
}
|
||||
|
||||
@@ -439,7 +548,7 @@ class EntityManager
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
@@ -448,9 +557,11 @@ class EntityManager
|
||||
public function persist($entity)
|
||||
{
|
||||
if ( ! is_object($entity)) {
|
||||
throw new \InvalidArgumentException(gettype($entity));
|
||||
throw ORMInvalidArgumentException::invalidObject('EntityManager#persist()' , $entity);
|
||||
}
|
||||
|
||||
$this->errorIfClosed();
|
||||
|
||||
$this->unitOfWork->persist($entity);
|
||||
}
|
||||
|
||||
@@ -465,9 +576,11 @@ class EntityManager
|
||||
public function remove($entity)
|
||||
{
|
||||
if ( ! is_object($entity)) {
|
||||
throw new \InvalidArgumentException(gettype($entity));
|
||||
throw ORMInvalidArgumentException::invalidObject('EntityManager#remove()' , $entity);
|
||||
}
|
||||
|
||||
$this->errorIfClosed();
|
||||
|
||||
$this->unitOfWork->remove($entity);
|
||||
}
|
||||
|
||||
@@ -480,9 +593,11 @@ class EntityManager
|
||||
public function refresh($entity)
|
||||
{
|
||||
if ( ! is_object($entity)) {
|
||||
throw new \InvalidArgumentException(gettype($entity));
|
||||
throw ORMInvalidArgumentException::invalidObject('EntityManager#refresh()' , $entity);
|
||||
}
|
||||
|
||||
$this->errorIfClosed();
|
||||
|
||||
$this->unitOfWork->refresh($entity);
|
||||
}
|
||||
|
||||
@@ -498,8 +613,9 @@ class EntityManager
|
||||
public function detach($entity)
|
||||
{
|
||||
if ( ! is_object($entity)) {
|
||||
throw new \InvalidArgumentException(gettype($entity));
|
||||
throw ORMInvalidArgumentException::invalidObject('EntityManager#detach()' , $entity);
|
||||
}
|
||||
|
||||
$this->unitOfWork->detach($entity);
|
||||
}
|
||||
|
||||
@@ -514,9 +630,11 @@ class EntityManager
|
||||
public function merge($entity)
|
||||
{
|
||||
if ( ! is_object($entity)) {
|
||||
throw new \InvalidArgumentException(gettype($entity));
|
||||
throw ORMInvalidArgumentException::invalidObject('EntityManager#merge()' , $entity);
|
||||
}
|
||||
|
||||
$this->errorIfClosed();
|
||||
|
||||
return $this->unitOfWork->merge($entity);
|
||||
}
|
||||
|
||||
@@ -556,19 +674,20 @@ class EntityManager
|
||||
public function getRepository($entityName)
|
||||
{
|
||||
$entityName = ltrim($entityName, '\\');
|
||||
|
||||
if (isset($this->repositories[$entityName])) {
|
||||
return $this->repositories[$entityName];
|
||||
}
|
||||
|
||||
$metadata = $this->getClassMetadata($entityName);
|
||||
$customRepositoryClassName = $metadata->customRepositoryClassName;
|
||||
$repositoryClassName = $metadata->customRepositoryClassName;
|
||||
|
||||
if ($customRepositoryClassName !== null) {
|
||||
$repository = new $customRepositoryClassName($this, $metadata);
|
||||
} else {
|
||||
$repository = new EntityRepository($this, $metadata);
|
||||
if ($repositoryClassName === null) {
|
||||
$repositoryClassName = $this->config->getDefaultRepositoryClassName();
|
||||
}
|
||||
|
||||
$repository = new $repositoryClassName($this, $metadata);
|
||||
|
||||
$this->repositories[$entityName] = $repository;
|
||||
|
||||
return $repository;
|
||||
@@ -582,15 +701,15 @@ class EntityManager
|
||||
*/
|
||||
public function contains($entity)
|
||||
{
|
||||
return $this->unitOfWork->isScheduledForInsert($entity) ||
|
||||
$this->unitOfWork->isInIdentityMap($entity) &&
|
||||
! $this->unitOfWork->isScheduledForDelete($entity);
|
||||
return $this->unitOfWork->isScheduledForInsert($entity)
|
||||
|| $this->unitOfWork->isInIdentityMap($entity)
|
||||
&& ! $this->unitOfWork->isScheduledForDelete($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the EventManager used by the EntityManager.
|
||||
*
|
||||
* @return Doctrine\Common\EventManager
|
||||
* @return \Doctrine\Common\EventManager
|
||||
*/
|
||||
public function getEventManager()
|
||||
{
|
||||
@@ -600,7 +719,7 @@ class EntityManager
|
||||
/**
|
||||
* Gets the Configuration used by the EntityManager.
|
||||
*
|
||||
* @return Doctrine\ORM\Configuration
|
||||
* @return \Doctrine\ORM\Configuration
|
||||
*/
|
||||
public function getConfiguration()
|
||||
{
|
||||
@@ -621,7 +740,7 @@ class EntityManager
|
||||
|
||||
/**
|
||||
* Check if the Entity manager is open or closed.
|
||||
*
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isOpen()
|
||||
@@ -632,7 +751,7 @@ class EntityManager
|
||||
/**
|
||||
* Gets the UnitOfWork used by the EntityManager to coordinate operations.
|
||||
*
|
||||
* @return Doctrine\ORM\UnitOfWork
|
||||
* @return \Doctrine\ORM\UnitOfWork
|
||||
*/
|
||||
public function getUnitOfWork()
|
||||
{
|
||||
@@ -646,7 +765,7 @@ class EntityManager
|
||||
* selectively iterate over the result.
|
||||
*
|
||||
* @param int $hydrationMode
|
||||
* @return Doctrine\ORM\Internal\Hydration\AbstractHydrator
|
||||
* @return \Doctrine\ORM\Internal\Hydration\AbstractHydrator
|
||||
*/
|
||||
public function getHydrator($hydrationMode)
|
||||
{
|
||||
@@ -661,32 +780,33 @@ class EntityManager
|
||||
* 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)
|
||||
{
|
||||
switch ($hydrationMode) {
|
||||
case Query::HYDRATE_OBJECT:
|
||||
$hydrator = new Internal\Hydration\ObjectHydrator($this);
|
||||
break;
|
||||
return new Internal\Hydration\ObjectHydrator($this);
|
||||
|
||||
case Query::HYDRATE_ARRAY:
|
||||
$hydrator = new Internal\Hydration\ArrayHydrator($this);
|
||||
break;
|
||||
return new Internal\Hydration\ArrayHydrator($this);
|
||||
|
||||
case Query::HYDRATE_SCALAR:
|
||||
$hydrator = new Internal\Hydration\ScalarHydrator($this);
|
||||
break;
|
||||
return new Internal\Hydration\ScalarHydrator($this);
|
||||
|
||||
case Query::HYDRATE_SINGLE_SCALAR:
|
||||
$hydrator = new Internal\Hydration\SingleScalarHydrator($this);
|
||||
break;
|
||||
return new Internal\Hydration\SingleScalarHydrator($this);
|
||||
|
||||
case Query::HYDRATE_SIMPLEOBJECT:
|
||||
return new Internal\Hydration\SimpleObjectHydrator($this);
|
||||
|
||||
default:
|
||||
if ($class = $this->config->getCustomHydrationMode($hydrationMode)) {
|
||||
$hydrator = new $class($this);
|
||||
break;
|
||||
if (($class = $this->config->getCustomHydrationMode($hydrationMode)) !== null) {
|
||||
return new $class($this);
|
||||
}
|
||||
throw ORMException::invalidHydrationMode($hydrationMode);
|
||||
}
|
||||
|
||||
return $hydrator;
|
||||
throw ORMException::invalidHydrationMode($hydrationMode);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -699,6 +819,18 @@ class EntityManager
|
||||
return $this->proxyFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to initialize a lazy loading proxy or persistent collection.
|
||||
*
|
||||
* This method is a no-op for other objects
|
||||
*
|
||||
* @param object $obj
|
||||
*/
|
||||
public function initializeObject($obj)
|
||||
{
|
||||
$this->unitOfWork->initializeObject($obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method to create EntityManager instances.
|
||||
*
|
||||
@@ -710,20 +842,61 @@ class EntityManager
|
||||
*/
|
||||
public static function create($conn, Configuration $config, EventManager $eventManager = null)
|
||||
{
|
||||
if (!$config->getMetadataDriverImpl()) {
|
||||
if ( ! $config->getMetadataDriverImpl()) {
|
||||
throw ORMException::missingMappingDriverImpl();
|
||||
}
|
||||
|
||||
if (is_array($conn)) {
|
||||
$conn = \Doctrine\DBAL\DriverManager::getConnection($conn, $config, ($eventManager ?: new EventManager()));
|
||||
} else if ($conn instanceof Connection) {
|
||||
if ($eventManager !== null && $conn->getEventManager() !== $eventManager) {
|
||||
throw ORMException::mismatchedEventManager();
|
||||
}
|
||||
} else {
|
||||
throw new \InvalidArgumentException("Invalid argument: " . $conn);
|
||||
switch (true) {
|
||||
case (is_array($conn)):
|
||||
$conn = \Doctrine\DBAL\DriverManager::getConnection(
|
||||
$conn, $config, ($eventManager ?: new EventManager())
|
||||
);
|
||||
break;
|
||||
|
||||
case ($conn instanceof Connection):
|
||||
if ($eventManager !== null && $conn->getEventManager() !== $eventManager) {
|
||||
throw ORMException::mismatchedEventManager();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \InvalidArgumentException("Invalid argument: " . $conn);
|
||||
}
|
||||
|
||||
return new EntityManager($conn, $config, $conn->getEventManager());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the enabled filters.
|
||||
*
|
||||
* @return FilterCollection The active filter collection.
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
if (null === $this->filterCollection) {
|
||||
$this->filterCollection = new FilterCollection($this);
|
||||
}
|
||||
|
||||
return $this->filterCollection;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the state of the filter collection is clean.
|
||||
*
|
||||
* @return boolean True, if the filter collection is clean.
|
||||
*/
|
||||
public function isFiltersStateClean()
|
||||
{
|
||||
return null === $this->filterCollection || $this->filterCollection->isClean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the Entity Manager has filters.
|
||||
*
|
||||
* @return True, if the EM has a filter collection.
|
||||
*/
|
||||
public function hasFilters()
|
||||
{
|
||||
return null !== $this->filterCollection;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
@@ -31,4 +31,4 @@ class EntityNotFoundException extends ORMException
|
||||
{
|
||||
parent::__construct('Entity was not found.');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,13 +13,19 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM;
|
||||
|
||||
use Doctrine\DBAL\LockMode;
|
||||
use Doctrine\Common\Persistence\ObjectRepository;
|
||||
|
||||
use Doctrine\Common\Collections\Selectable;
|
||||
use Doctrine\Common\Collections\Criteria;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\ExpressionBuilder;
|
||||
|
||||
/**
|
||||
* An EntityRepository serves as a repository for entities with generic as well as
|
||||
@@ -34,7 +40,7 @@ use Doctrine\DBAL\LockMode;
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class EntityRepository
|
||||
class EntityRepository implements ObjectRepository, Selectable
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
@@ -47,7 +53,7 @@ class EntityRepository
|
||||
protected $_em;
|
||||
|
||||
/**
|
||||
* @var Doctrine\ORM\Mapping\ClassMetadata
|
||||
* @var \Doctrine\ORM\Mapping\ClassMetadata
|
||||
*/
|
||||
protected $_class;
|
||||
|
||||
@@ -60,8 +66,8 @@ class EntityRepository
|
||||
public function __construct($em, Mapping\ClassMetadata $class)
|
||||
{
|
||||
$this->_entityName = $class->name;
|
||||
$this->_em = $em;
|
||||
$this->_class = $class;
|
||||
$this->_em = $em;
|
||||
$this->_class = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -77,6 +83,32 @@ class EntityRepository
|
||||
->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));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a native SQL query.
|
||||
*
|
||||
* @param string $queryName
|
||||
* @return NativeQuery
|
||||
*/
|
||||
public function createNativeNamedQuery($queryName)
|
||||
{
|
||||
$queryMapping = $this->_class->getNamedNativeQuery($queryName);
|
||||
$rsm = new Query\ResultSetMappingBuilder($this->_em);
|
||||
$rsm->addNamedNativeQueryMapping($this->_class, $queryMapping);
|
||||
|
||||
return $this->_em->createNativeQuery($queryMapping['query'], $rsm);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the repository, causing all managed entities to become detached.
|
||||
*/
|
||||
@@ -88,50 +120,15 @@ class EntityRepository
|
||||
/**
|
||||
* Finds an entity by its primary key / identifier.
|
||||
*
|
||||
* @param $id The identifier.
|
||||
* @param int $lockMode
|
||||
* @param int $lockVersion
|
||||
* @param mixed $id The identifier.
|
||||
* @param integer $lockMode
|
||||
* @param integer $lockVersion
|
||||
*
|
||||
* @return object The entity.
|
||||
*/
|
||||
public function find($id, $lockMode = LockMode::NONE, $lockVersion = null)
|
||||
{
|
||||
// Check identity map first
|
||||
if ($entity = $this->_em->getUnitOfWork()->tryGetById($id, $this->_class->rootEntityName)) {
|
||||
if (!($entity instanceof $this->_class->name)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if ($lockMode != LockMode::NONE) {
|
||||
$this->_em->lock($entity, $lockMode, $lockVersion);
|
||||
}
|
||||
|
||||
return $entity; // Hit!
|
||||
}
|
||||
|
||||
if ( ! is_array($id) || count($id) <= 1) {
|
||||
// @todo FIXME: Not correct. Relies on specific order.
|
||||
$value = is_array($id) ? array_values($id) : array($id);
|
||||
$id = array_combine($this->_class->identifier, $value);
|
||||
}
|
||||
|
||||
if ($lockMode == LockMode::NONE) {
|
||||
return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($id);
|
||||
} else if ($lockMode == LockMode::OPTIMISTIC) {
|
||||
if (!$this->_class->isVersioned) {
|
||||
throw OptimisticLockException::notVersioned($this->_entityName);
|
||||
}
|
||||
$entity = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($id);
|
||||
|
||||
$this->_em->getUnitOfWork()->lock($entity, $lockMode, $lockVersion);
|
||||
|
||||
return $entity;
|
||||
} else {
|
||||
if (!$this->_em->getConnection()->isTransactionActive()) {
|
||||
throw TransactionRequiredException::transactionRequired();
|
||||
}
|
||||
|
||||
return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($id, null, null, array(), $lockMode);
|
||||
}
|
||||
return $this->_em->find($this->_entityName, $id, $lockMode, $lockVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,11 +145,16 @@ class EntityRepository
|
||||
* Finds entities by a set of criteria.
|
||||
*
|
||||
* @param array $criteria
|
||||
* @return array
|
||||
* @param array|null $orderBy
|
||||
* @param int|null $limit
|
||||
* @param int|null $offset
|
||||
* @return array The objects.
|
||||
*/
|
||||
public function findBy(array $criteria)
|
||||
public function findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
{
|
||||
return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->loadAll($criteria);
|
||||
$persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);
|
||||
|
||||
return $persister->loadAll($criteria, $orderBy, $limit, $offset);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,7 +165,9 @@ class EntityRepository
|
||||
*/
|
||||
public function findOneBy(array $criteria)
|
||||
{
|
||||
return $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName)->load($criteria);
|
||||
$persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);
|
||||
|
||||
return $persister->load($criteria, null, null, array(), 0, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,31 +180,50 @@ class EntityRepository
|
||||
*/
|
||||
public function __call($method, $arguments)
|
||||
{
|
||||
if (substr($method, 0, 6) == 'findBy') {
|
||||
$by = substr($method, 6, strlen($method));
|
||||
$method = 'findBy';
|
||||
} else if (substr($method, 0, 9) == 'findOneBy') {
|
||||
$by = substr($method, 9, strlen($method));
|
||||
$method = 'findOneBy';
|
||||
} else {
|
||||
throw new \BadMethodCallException(
|
||||
"Undefined method '$method'. The method name must start with ".
|
||||
"either findBy or findOneBy!"
|
||||
);
|
||||
switch (true) {
|
||||
case (0 === strpos($method, 'findBy')):
|
||||
$by = substr($method, 6);
|
||||
$method = 'findBy';
|
||||
break;
|
||||
|
||||
case (0 === strpos($method, 'findOneBy')):
|
||||
$by = substr($method, 9);
|
||||
$method = 'findOneBy';
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new \BadMethodCallException(
|
||||
"Undefined method '$method'. The method name must start with ".
|
||||
"either findBy or findOneBy!"
|
||||
);
|
||||
}
|
||||
|
||||
if ( !isset($arguments[0])) {
|
||||
// we dont even want to allow null at this point, because we cannot (yet) transform it into IS NULL.
|
||||
throw ORMException::findByRequiresParameter($method.$by);
|
||||
if (empty($arguments)) {
|
||||
throw ORMException::findByRequiresParameter($method . $by);
|
||||
}
|
||||
|
||||
$fieldName = lcfirst(\Doctrine\Common\Util\Inflector::classify($by));
|
||||
|
||||
if ($this->_class->hasField($fieldName) || $this->_class->hasAssociation($fieldName)) {
|
||||
return $this->$method(array($fieldName => $arguments[0]));
|
||||
} else {
|
||||
throw ORMException::invalidFindByCall($this->_entityName, $fieldName, $method.$by);
|
||||
switch (count($arguments)) {
|
||||
case 1:
|
||||
return $this->$method(array($fieldName => $arguments[0]));
|
||||
|
||||
case 2:
|
||||
return $this->$method(array($fieldName => $arguments[0]), $arguments[1]);
|
||||
|
||||
case 3:
|
||||
return $this->$method(array($fieldName => $arguments[0]), $arguments[1], $arguments[2]);
|
||||
|
||||
case 4;
|
||||
return $this->$method(array($fieldName => $arguments[0]), $arguments[1], $arguments[2], $arguments[3]);
|
||||
|
||||
default:
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
throw ORMException::invalidFindByCall($this->_entityName, $fieldName, $method.$by);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,6 +234,14 @@ class EntityRepository
|
||||
return $this->_entityName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getClassName()
|
||||
{
|
||||
return $this->getEntityName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EntityManager
|
||||
*/
|
||||
@@ -226,4 +257,20 @@ class EntityRepository
|
||||
{
|
||||
return $this->_class;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Select all elements from a selectable that match the expression and
|
||||
* return a new collection containing these elements.
|
||||
*
|
||||
* @param \Doctrine\Common\Collections\Criteria $criteria
|
||||
*
|
||||
* @return \Doctrine\Common\Collections\Collection
|
||||
*/
|
||||
public function matching(Criteria $criteria)
|
||||
{
|
||||
$persister = $this->_em->getUnitOfWork()->getEntityPersister($this->_entityName);
|
||||
|
||||
return new ArrayCollection($persister->loadCriteria($criteria));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -13,48 +13,65 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\Common\EventArgs;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
|
||||
/**
|
||||
* Lifecycle Events are triggered by the UnitOfWork during lifecycle transitions
|
||||
* of entities.
|
||||
*
|
||||
* @since 2.0
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.de>
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class LifecycleEventArgs extends \Doctrine\Common\EventArgs
|
||||
class LifecycleEventArgs extends EventArgs
|
||||
{
|
||||
/**
|
||||
* @var EntityManager
|
||||
* @var \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
private $_em;
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* @var object
|
||||
*/
|
||||
private $_entity;
|
||||
|
||||
public function __construct($entity, $em)
|
||||
private $entity;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param object $entity
|
||||
* @param \Doctrine\ORM\EntityManager $em
|
||||
*/
|
||||
public function __construct($entity, EntityManager $em)
|
||||
{
|
||||
$this->_entity = $entity;
|
||||
$this->_em = $em;
|
||||
}
|
||||
|
||||
public function getEntity()
|
||||
{
|
||||
return $this->_entity;
|
||||
$this->entity = $entity;
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EntityManager
|
||||
* Retrieve associated Entity.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function getEntity()
|
||||
{
|
||||
return $this->entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve associated EntityManager.
|
||||
*
|
||||
* @return \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
public function getEntityManager()
|
||||
{
|
||||
return $this->_em;
|
||||
return $this->em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,25 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\Common\EventArgs;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
|
||||
@@ -11,32 +27,36 @@ use Doctrine\ORM\EntityManager;
|
||||
* Class that holds event arguments for a loadMetadata event.
|
||||
*
|
||||
* @author Jonathan H. Wage <jonwage@gmail.com>
|
||||
* @since 2.0
|
||||
* @since 2.0
|
||||
*/
|
||||
class LoadClassMetadataEventArgs extends EventArgs
|
||||
{
|
||||
/**
|
||||
* @var ClassMetadata
|
||||
* @var \Doctrine\ORM\Mapping\ClassMetadata
|
||||
*/
|
||||
private $classMetadata;
|
||||
|
||||
/**
|
||||
* @var EntityManager
|
||||
* @var \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* @param ClassMetadataInfo $classMetadata
|
||||
* @param EntityManager $em
|
||||
* Constructor.
|
||||
*
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadataInfo $classMetadata
|
||||
* @param \Doctrine\ORM\EntityManager $em
|
||||
*/
|
||||
public function __construct(ClassMetadataInfo $classMetadata, EntityManager $em)
|
||||
{
|
||||
$this->classMetadata = $classMetadata;
|
||||
$this->em = $em;
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClassMetadataInfo
|
||||
* Retrieve associated ClassMetadata.
|
||||
*
|
||||
* @return \Doctrine\ORM\Mapping\ClassMetadataInfo
|
||||
*/
|
||||
public function getClassMetadata()
|
||||
{
|
||||
@@ -44,7 +64,9 @@ class LoadClassMetadataEventArgs extends EventArgs
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EntityManager
|
||||
* Retrieve associated EntityManager.
|
||||
*
|
||||
* @return \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
public function getEntityManager()
|
||||
{
|
||||
|
||||
84
lib/Doctrine/ORM/Event/OnClearEventArgs.php
Normal file
84
lib/Doctrine/ORM/Event/OnClearEventArgs.php
Normal file
@@ -0,0 +1,84 @@
|
||||
<?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 MIT license. 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.org
|
||||
* @since 2.0
|
||||
* @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;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $entityClass;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \Doctrine\ORM\EntityManager $em
|
||||
* @param string $entityClass Optional entity class
|
||||
*/
|
||||
public function __construct($em, $entityClass = null)
|
||||
{
|
||||
$this->em = $em;
|
||||
$this->entityClass = $entityClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve associated EntityManager.
|
||||
*
|
||||
* @return \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
public function getEntityManager()
|
||||
{
|
||||
return $this->em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Name of the entity class that is cleared, or empty if all are cleared.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEntityClass()
|
||||
{
|
||||
return $this->entityClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if event clears all entities.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function clearsAllEntities()
|
||||
{
|
||||
return ($this->entityClass === null);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
<?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
|
||||
@@ -15,64 +13,72 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
|
||||
/**
|
||||
* Provides event arguments for the preFlush event.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.com
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @author Roman Borschel <roman@code-factory.de>
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class OnFlushEventArgs extends \Doctrine\Common\EventArgs
|
||||
{
|
||||
/**
|
||||
* @var EntityManager
|
||||
* @var Doctirne\ORM\EntityManager
|
||||
*/
|
||||
private $_em;
|
||||
|
||||
//private $_entitiesToPersist = array();
|
||||
//private $_entitiesToRemove = array();
|
||||
|
||||
public function __construct($em)
|
||||
private $em;
|
||||
|
||||
//private $entitiesToPersist = array();
|
||||
//private $entitiesToRemove = array();
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \Doctrine\ORM\EntityManager $em
|
||||
*/
|
||||
public function __construct(EntityManager $em)
|
||||
{
|
||||
$this->_em = $em;
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EntityManager
|
||||
* Retrieve associated EntityManager.
|
||||
*
|
||||
* @return \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
public function getEntityManager()
|
||||
{
|
||||
return $this->_em;
|
||||
return $this->em;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
public function addEntityToPersist($entity)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function addEntityToRemove($entity)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function addEntityToUpdate($entity)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public function getEntitiesToPersist()
|
||||
{
|
||||
return $this->_entitiesToPersist;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
58
lib/Doctrine/ORM/Event/PostFlushEventArgs.php
Normal file
58
lib/Doctrine/ORM/Event/PostFlushEventArgs.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Doctrine\Common\EventArgs;
|
||||
|
||||
/**
|
||||
* Provides event arguments for the postFlush event.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @author Daniel Freudenberger <df@rebuy.de>
|
||||
*/
|
||||
class PostFlushEventArgs extends EventArgs
|
||||
{
|
||||
/**
|
||||
* @var \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
private $em;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param \Doctrine\ORM\EntityManager $em
|
||||
*/
|
||||
public function __construct(EntityManager $em)
|
||||
{
|
||||
$this->em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve associated EntityManager.
|
||||
*
|
||||
* @return \Doctrine\ORM\EntityManager
|
||||
*/
|
||||
public function getEntityManager()
|
||||
{
|
||||
return $this->em;
|
||||
}
|
||||
}
|
||||
50
lib/Doctrine/ORM/Event/PreFlushEventArgs.php
Normal file
50
lib/Doctrine/ORM/Event/PreFlushEventArgs.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
/**
|
||||
* Provides event arguments for the preFlush event.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.com
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.de>
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class PreFlushEventArgs extends \Doctrine\Common\EventArgs
|
||||
{
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $_em;
|
||||
|
||||
public function __construct($em)
|
||||
{
|
||||
$this->_em = $em;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return EntityManager
|
||||
*/
|
||||
public function getEntityManager()
|
||||
{
|
||||
return $this->_em;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,21 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Event;
|
||||
|
||||
@@ -8,55 +25,63 @@ use Doctrine\Common\EventArgs,
|
||||
/**
|
||||
* Class that holds event arguments for a preInsert/preUpdate event.
|
||||
*
|
||||
* @author Guilherme Blanco <guilehrmeblanco@hotmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @since 2.0
|
||||
* @since 2.0
|
||||
*/
|
||||
class PreUpdateEventArgs extends LifecycleEventArgs
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $_entityChangeSet;
|
||||
private $entityChangeSet;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*
|
||||
* @param object $entity
|
||||
* @param EntityManager $em
|
||||
* @param \Doctrine\ORM\EntityManager $em
|
||||
* @param array $changeSet
|
||||
*/
|
||||
public function __construct($entity, $em, array &$changeSet)
|
||||
public function __construct($entity, EntityManager $em, array &$changeSet)
|
||||
{
|
||||
parent::__construct($entity, $em);
|
||||
$this->_entityChangeSet = &$changeSet;
|
||||
}
|
||||
|
||||
public function getEntityChangeSet()
|
||||
{
|
||||
return $this->_entityChangeSet;
|
||||
$this->entityChangeSet = &$changeSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Field has a changeset?
|
||||
* Retrieve entity changeset.
|
||||
*
|
||||
* @return bool
|
||||
* @return array
|
||||
*/
|
||||
public function getEntityChangeSet()
|
||||
{
|
||||
return $this->entityChangeSet;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if field has a changeset.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function hasChangedField($field)
|
||||
{
|
||||
return isset($this->_entityChangeSet[$field]);
|
||||
return isset($this->entityChangeSet[$field]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the old value of the changeset of the changed field.
|
||||
*
|
||||
*
|
||||
* @param string $field
|
||||
* @return mixed
|
||||
*/
|
||||
public function getOldValue($field)
|
||||
{
|
||||
$this->_assertValidField($field);
|
||||
$this->assertValidField($field);
|
||||
|
||||
return $this->_entityChangeSet[$field][0];
|
||||
return $this->entityChangeSet[$field][0];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,31 +92,37 @@ class PreUpdateEventArgs extends LifecycleEventArgs
|
||||
*/
|
||||
public function getNewValue($field)
|
||||
{
|
||||
$this->_assertValidField($field);
|
||||
$this->assertValidField($field);
|
||||
|
||||
return $this->_entityChangeSet[$field][1];
|
||||
return $this->entityChangeSet[$field][1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the new value of this field.
|
||||
*
|
||||
*
|
||||
* @param string $field
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setNewValue($field, $value)
|
||||
{
|
||||
$this->_assertValidField($field);
|
||||
$this->assertValidField($field);
|
||||
|
||||
$this->_entityChangeSet[$field][1] = $value;
|
||||
$this->entityChangeSet[$field][1] = $value;
|
||||
}
|
||||
|
||||
private function _assertValidField($field)
|
||||
/**
|
||||
* Assert the field exists in changeset.
|
||||
*
|
||||
* @param string $field
|
||||
*/
|
||||
private function assertValidField($field)
|
||||
{
|
||||
if (!isset($this->_entityChangeSet[$field])) {
|
||||
throw new \InvalidArgumentException(
|
||||
"Field '".$field."' is not a valid field of the entity ".
|
||||
"'".get_class($this->getEntity())."' in PreInsertUpdateEventArgs."
|
||||
);
|
||||
if ( ! isset($this->entityChangeSet[$field])) {
|
||||
throw new \InvalidArgumentException(sprintf(
|
||||
'Field "%s" is not a valid field of the entity "%s" in PreUpdateEventArgs.',
|
||||
$field,
|
||||
get_class($this->getEntity())
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<?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
|
||||
@@ -15,7 +13,7 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
@@ -35,55 +33,55 @@ final class Events
|
||||
/**
|
||||
* The preRemove event occurs for a given entity before the respective
|
||||
* EntityManager remove operation for that entity is executed.
|
||||
*
|
||||
*
|
||||
* This is an entity lifecycle event.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const preRemove = 'preRemove';
|
||||
/**
|
||||
* The postRemove event occurs for an entity after the entity has
|
||||
* The postRemove event occurs for an entity after the entity has
|
||||
* been deleted. It will be invoked after the database delete operations.
|
||||
*
|
||||
*
|
||||
* This is an entity lifecycle event.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const postRemove = 'postRemove';
|
||||
/**
|
||||
* The prePersist event occurs for a given entity before the respective
|
||||
* EntityManager persist operation for that entity is executed.
|
||||
*
|
||||
*
|
||||
* This is an entity lifecycle event.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const prePersist = 'prePersist';
|
||||
/**
|
||||
* The postPersist event occurs for an entity after the entity has
|
||||
* The postPersist event occurs for an entity after the entity has
|
||||
* been made persistent. It will be invoked after the database insert operations.
|
||||
* Generated primary key values are available in the postPersist event.
|
||||
*
|
||||
*
|
||||
* This is an entity lifecycle event.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const postPersist = 'postPersist';
|
||||
/**
|
||||
* The preUpdate event occurs before the database update operations to
|
||||
* entity data.
|
||||
*
|
||||
* The preUpdate event occurs before the database update operations to
|
||||
* entity data.
|
||||
*
|
||||
* This is an entity lifecycle event.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const preUpdate = 'preUpdate';
|
||||
/**
|
||||
* The postUpdate event occurs after the database update operations to
|
||||
* entity data.
|
||||
*
|
||||
* The postUpdate event occurs after the database update operations to
|
||||
* entity data.
|
||||
*
|
||||
* This is an entity lifecycle event.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const postUpdate = 'postUpdate';
|
||||
@@ -91,32 +89,58 @@ final class Events
|
||||
* The postLoad event occurs for an entity after the entity has been loaded
|
||||
* into the current EntityManager from the database or after the refresh operation
|
||||
* has been applied to it.
|
||||
*
|
||||
*
|
||||
* Note that the postLoad event occurs for an entity before any associations have been
|
||||
* initialized. Therefore it is not safe to access associations in a postLoad callback
|
||||
* or event handler.
|
||||
*
|
||||
*
|
||||
* This is an entity lifecycle event.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const postLoad = 'postLoad';
|
||||
/**
|
||||
* The loadClassMetadata event occurs after the mapping metadata for a class
|
||||
* has been loaded from a mapping source (annotations/xml/yaml).
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const loadClassMetadata = 'loadClassMetadata';
|
||||
|
||||
|
||||
/**
|
||||
* The preFlush event occurs when the EntityManager#flush() operation is invoked,
|
||||
* but before any changes to managed entites have been calculated. This event is
|
||||
* always raised right after EntityManager#flush() call.
|
||||
*/
|
||||
const preFlush = 'preFlush';
|
||||
|
||||
/**
|
||||
* The onFlush event occurs when the EntityManager#flush() operation is invoked,
|
||||
* after any changes to managed entities have been determined but before any
|
||||
* actual database operations are executed. The event is only raised if there is
|
||||
* actually something to do for the underlying UnitOfWork. If nothing needs to be done,
|
||||
* the onFlush event is not raised.
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const onFlush = 'onFlush';
|
||||
}
|
||||
|
||||
/**
|
||||
* The postFlush event occurs when the EntityManager#flush() operation is invoked and
|
||||
* after all actual database operations are executed successfully. The event is only raised if there is
|
||||
* actually something to do for the underlying UnitOfWork. If nothing needs to be done,
|
||||
* the postFlush event is not raised. The event won't be raised if an error occurs during the
|
||||
* flush operation.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const postFlush = 'postFlush';
|
||||
|
||||
/**
|
||||
* The onClear event occurs when the EntityManager#clear() operation is invoked,
|
||||
* after all references to entities have been removed from the unit of work.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const onClear = 'onClear';
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
@@ -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);
|
||||
@@ -35,7 +35,7 @@ abstract class AbstractIdGenerator
|
||||
* Gets whether this generator is a post-insert generator which means that
|
||||
* {@link generate()} must be called after the entity has been inserted
|
||||
* into the database.
|
||||
*
|
||||
*
|
||||
* By default, this method returns FALSE. Generators that have this requirement
|
||||
* must override this method and return TRUE.
|
||||
*
|
||||
@@ -45,4 +45,4 @@ abstract class AbstractIdGenerator
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
@@ -42,28 +42,29 @@ class AssignedGenerator extends AbstractIdGenerator
|
||||
*/
|
||||
public function generate(EntityManager $em, $entity)
|
||||
{
|
||||
$class = $em->getClassMetadata(get_class($entity));
|
||||
$class = $em->getClassMetadata(get_class($entity));
|
||||
$idFields = $class->getIdentifierFieldNames();
|
||||
$identifier = array();
|
||||
if ($class->isIdentifierComposite) {
|
||||
$idFields = $class->getIdentifierFieldNames();
|
||||
foreach ($idFields as $idField) {
|
||||
$value = $class->getReflectionProperty($idField)->getValue($entity);
|
||||
if (isset($value)) {
|
||||
$identifier[$idField] = $value;
|
||||
} else {
|
||||
throw ORMException::entityMissingAssignedId($entity);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$idField = $class->identifier[0];
|
||||
|
||||
foreach ($idFields as $idField) {
|
||||
$value = $class->reflFields[$idField]->getValue($entity);
|
||||
if (isset($value)) {
|
||||
$identifier[$idField] = $value;
|
||||
} else {
|
||||
throw ORMException::entityMissingAssignedId($entity);
|
||||
|
||||
if ( ! isset($value)) {
|
||||
throw ORMException::entityMissingAssignedIdForField($entity, $idField);
|
||||
}
|
||||
|
||||
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.
|
||||
$value = current($em->getUnitOfWork()->getEntityIdentifier($value));
|
||||
}
|
||||
|
||||
$identifier[$idField] = $value;
|
||||
}
|
||||
|
||||
|
||||
return $identifier;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
@@ -46,7 +46,7 @@ class IdentityGenerator extends AbstractIdGenerator
|
||||
*/
|
||||
public function generate(EntityManager $em, $entity)
|
||||
{
|
||||
return $em->getConnection()->lastInsertId($this->_seqName);
|
||||
return (int)$em->getConnection()->lastInsertId($this->_seqName);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -56,4 +56,4 @@ class IdentityGenerator extends AbstractIdGenerator
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
@@ -46,7 +46,7 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
|
||||
$this->_sequenceName = $sequenceName;
|
||||
$this->_allocationSize = $allocationSize;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generates an ID for the given entity.
|
||||
*
|
||||
@@ -59,10 +59,12 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
|
||||
if ($this->_maxValue === null || $this->_nextValue == $this->_maxValue) {
|
||||
// Allocate new values
|
||||
$conn = $em->getConnection();
|
||||
$sql = $conn->getDatabasePlatform()->getSequenceNextValSQL($this->_sequenceName);
|
||||
$this->_nextValue = $conn->fetchColumn($sql);
|
||||
$this->_maxValue = $this->_nextValue + $this->_allocationSize;
|
||||
$sql = $conn->getDatabasePlatform()->getSequenceNextValSQL($this->_sequenceName);
|
||||
|
||||
$this->_nextValue = (int)$conn->fetchColumn($sql);
|
||||
$this->_maxValue = $this->_nextValue + $this->_allocationSize;
|
||||
}
|
||||
|
||||
return $this->_nextValue++;
|
||||
}
|
||||
|
||||
@@ -90,13 +92,14 @@ class SequenceGenerator extends AbstractIdGenerator implements Serializable
|
||||
{
|
||||
return serialize(array(
|
||||
'allocationSize' => $this->_allocationSize,
|
||||
'sequenceName' => $this->_sequenceName
|
||||
'sequenceName' => $this->_sequenceName
|
||||
));
|
||||
}
|
||||
|
||||
public function unserialize($serialized)
|
||||
{
|
||||
$array = unserialize($serialized);
|
||||
|
||||
$this->_sequenceName = $array['sequenceName'];
|
||||
$this->_allocationSize = $array['allocationSize'];
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
@@ -50,11 +50,12 @@ class TableGenerator extends AbstractIdGenerator
|
||||
if ($this->_maxValue === null || $this->_nextValue == $this->_maxValue) {
|
||||
// Allocate new values
|
||||
$conn = $em->getConnection();
|
||||
if ($conn->getTransactionNestingLevel() == 0) {
|
||||
|
||||
if ($conn->getTransactionNestingLevel() === 0) {
|
||||
// use select for update
|
||||
$sql = $conn->getDatabasePlatform()->getTableHiLoCurrentValSql($this->_tableName, $this->_sequenceName);
|
||||
$sql = $conn->getDatabasePlatform()->getTableHiLoCurrentValSql($this->_tableName, $this->_sequenceName);
|
||||
$currentLevel = $conn->fetchColumn($sql);
|
||||
|
||||
if ($currentLevel != null) {
|
||||
$this->_nextValue = $currentLevel;
|
||||
$this->_maxValue = $this->_nextValue + $this->_allocationSize;
|
||||
@@ -62,7 +63,7 @@ class TableGenerator extends AbstractIdGenerator
|
||||
$updateSql = $conn->getDatabasePlatform()->getTableHiLoUpdateNextValSql(
|
||||
$this->_tableName, $this->_sequenceName, $this->_allocationSize
|
||||
);
|
||||
|
||||
|
||||
if ($conn->executeUpdate($updateSql, array(1 => $currentLevel, 2 => $currentLevel+1)) !== 1) {
|
||||
// no affected rows, concurrency issue, throw exception
|
||||
}
|
||||
@@ -74,6 +75,7 @@ class TableGenerator extends AbstractIdGenerator
|
||||
// or do we want to work with table locks exclusively?
|
||||
}
|
||||
}
|
||||
|
||||
return $this->_nextValue++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
48
lib/Doctrine/ORM/Id/UuidGenerator.php
Normal file
48
lib/Doctrine/ORM/Id/UuidGenerator.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Id;
|
||||
|
||||
use Serializable, Doctrine\ORM\EntityManager;
|
||||
|
||||
/**
|
||||
* Represents an ID generator that uses the database UUID expression
|
||||
*
|
||||
* @since 2.3
|
||||
* @author Maarten de Keizer <m.de.keizer@markei.nl>
|
||||
*/
|
||||
class UuidGenerator extends AbstractIdGenerator
|
||||
{
|
||||
|
||||
/**
|
||||
* Generates an ID for the given entity.
|
||||
*
|
||||
* @param Doctrine\ORM\EntityManager $em The EntityManager to user
|
||||
* @param object $entity
|
||||
* @return string The generated value.
|
||||
* @override
|
||||
*/
|
||||
public function generate(EntityManager $em, $entity)
|
||||
{
|
||||
$conn = $em->getConnection();
|
||||
$sql = 'SELECT ' . $conn->getDatabasePlatform()->getGuidExpression();
|
||||
return $conn->query($sql)->fetchColumn(0);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
@@ -23,20 +23,21 @@ namespace Doctrine\ORM\Internal;
|
||||
* The CommitOrderCalculator is used by the UnitOfWork to sort out the
|
||||
* correct order in which changes to entities need to be persisted.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
*/
|
||||
class CommitOrderCalculator
|
||||
{
|
||||
const NOT_VISITED = 1;
|
||||
const IN_PROGRESS = 2;
|
||||
const VISITED = 3;
|
||||
|
||||
|
||||
private $_nodeStates = array();
|
||||
private $_classes = array(); // The nodes to sort
|
||||
private $_relatedClasses = array();
|
||||
private $_sorted = array();
|
||||
|
||||
|
||||
/**
|
||||
* Clears the current graph.
|
||||
*
|
||||
@@ -47,10 +48,10 @@ class CommitOrderCalculator
|
||||
$this->_classes =
|
||||
$this->_relatedClasses = array();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets a valid commit order for all current nodes.
|
||||
*
|
||||
*
|
||||
* Uses a depth-first search (DFS) to traverse the graph.
|
||||
* The desired topological sorting is the reverse postorder of these searches.
|
||||
*
|
||||
@@ -60,17 +61,16 @@ class CommitOrderCalculator
|
||||
{
|
||||
// Check whether we need to do anything. 0 or 1 node is easy.
|
||||
$nodeCount = count($this->_classes);
|
||||
if ($nodeCount == 0) {
|
||||
return array();
|
||||
} else if ($nodeCount == 1) {
|
||||
return array_values($this->_classes);
|
||||
|
||||
if ($nodeCount <= 1) {
|
||||
return ($nodeCount == 1) ? array_values($this->_classes) : array();
|
||||
}
|
||||
|
||||
|
||||
// Init
|
||||
foreach ($this->_classes as $node) {
|
||||
$this->_nodeStates[$node->name] = self::NOT_VISITED;
|
||||
}
|
||||
|
||||
|
||||
// Go
|
||||
foreach ($this->_classes as $node) {
|
||||
if ($this->_nodeStates[$node->name] == self::NOT_VISITED) {
|
||||
@@ -100,19 +100,19 @@ class CommitOrderCalculator
|
||||
$this->_nodeStates[$node->name] = self::VISITED;
|
||||
$this->_sorted[] = $node;
|
||||
}
|
||||
|
||||
|
||||
public function addDependency($fromClass, $toClass)
|
||||
{
|
||||
$this->_relatedClasses[$fromClass->name][] = $toClass;
|
||||
}
|
||||
|
||||
|
||||
public function hasClass($className)
|
||||
{
|
||||
return isset($this->_classes[$className]);
|
||||
}
|
||||
|
||||
|
||||
public function addClass($class)
|
||||
{
|
||||
$this->_classes[$class->name] = $class;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
@@ -22,34 +22,37 @@ namespace Doctrine\ORM\Internal\Hydration;
|
||||
use PDO,
|
||||
Doctrine\DBAL\Connection,
|
||||
Doctrine\DBAL\Types\Type,
|
||||
Doctrine\ORM\EntityManager;
|
||||
Doctrine\ORM\EntityManager,
|
||||
Doctrine\ORM\Events,
|
||||
Doctrine\ORM\Mapping\ClassMetadata;
|
||||
|
||||
/**
|
||||
* Base class for all hydrators. A hydrator is a class that provides some form
|
||||
* of transformation of an SQL result set into another structure.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
* @author Konsta Vesterinen <kvesteri@cc.hut.fi>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @author Guilherme Blanco <guilhermeblanoc@hotmail.com>
|
||||
*/
|
||||
abstract class AbstractHydrator
|
||||
{
|
||||
/** @var ResultSetMapping The ResultSetMapping. */
|
||||
/** @var \Doctrine\ORM\Query\ResultSetMapping The ResultSetMapping. */
|
||||
protected $_rsm;
|
||||
|
||||
/** @var EntityManager The EntityManager instance. */
|
||||
protected $_em;
|
||||
|
||||
/** @var AbstractPlatform The dbms Platform instance */
|
||||
/** @var \Doctrine\DBAL\Platforms\AbstractPlatform The dbms Platform instance */
|
||||
protected $_platform;
|
||||
|
||||
/** @var UnitOfWork The UnitOfWork of the associated EntityManager. */
|
||||
/** @var \Doctrine\ORM\UnitOfWork The UnitOfWork of the associated EntityManager. */
|
||||
protected $_uow;
|
||||
|
||||
/** @var array The cache used during row-by-row hydration. */
|
||||
protected $_cache = array();
|
||||
|
||||
/** @var Statement The statement that provides the data to hydrate. */
|
||||
/** @var \Doctrine\DBAL\Driver\Statement The statement that provides the data to hydrate. */
|
||||
protected $_stmt;
|
||||
|
||||
/** @var array The query hints. */
|
||||
@@ -58,13 +61,13 @@ 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)
|
||||
{
|
||||
$this->_em = $em;
|
||||
$this->_em = $em;
|
||||
$this->_platform = $em->getConnection()->getDatabasePlatform();
|
||||
$this->_uow = $em->getUnitOfWork();
|
||||
$this->_uow = $em->getUnitOfWork();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,14 +75,20 @@ abstract class AbstractHydrator
|
||||
*
|
||||
* @param object $stmt
|
||||
* @param object $resultSetMapping
|
||||
*
|
||||
* @return IterableResult
|
||||
*/
|
||||
public function iterate($stmt, $resultSetMapping, array $hints = array())
|
||||
{
|
||||
$this->_stmt = $stmt;
|
||||
$this->_rsm = $resultSetMapping;
|
||||
$this->_stmt = $stmt;
|
||||
$this->_rsm = $resultSetMapping;
|
||||
$this->_hints = $hints;
|
||||
$this->_prepare();
|
||||
|
||||
$evm = $this->_em->getEventManager();
|
||||
$evm->addEventListener(array(Events::onClear), $this);
|
||||
|
||||
$this->prepare();
|
||||
|
||||
return new IterableResult($this);
|
||||
}
|
||||
|
||||
@@ -88,16 +97,21 @@ abstract class AbstractHydrator
|
||||
*
|
||||
* @param object $stmt
|
||||
* @param object $resultSetMapping
|
||||
* @param array $hints
|
||||
* @return mixed
|
||||
*/
|
||||
public function hydrateAll($stmt, $resultSetMapping, array $hints = array())
|
||||
{
|
||||
$this->_stmt = $stmt;
|
||||
$this->_rsm = $resultSetMapping;
|
||||
$this->_stmt = $stmt;
|
||||
$this->_rsm = $resultSetMapping;
|
||||
$this->_hints = $hints;
|
||||
$this->_prepare();
|
||||
$result = $this->_hydrateAll();
|
||||
$this->_cleanup();
|
||||
|
||||
$this->prepare();
|
||||
|
||||
$result = $this->hydrateAllData();
|
||||
|
||||
$this->cleanup();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -110,12 +124,17 @@ abstract class AbstractHydrator
|
||||
public function hydrateRow()
|
||||
{
|
||||
$row = $this->_stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
||||
if ( ! $row) {
|
||||
$this->_cleanup();
|
||||
$this->cleanup();
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$result = array();
|
||||
$this->_hydrateRow($row, $this->_cache, $result);
|
||||
|
||||
$this->hydrateRowData($row, $this->_cache, $result);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
@@ -123,16 +142,17 @@ abstract class AbstractHydrator
|
||||
* Excutes one-time preparation tasks, once each time hydration is started
|
||||
* through {@link hydrateAll} or {@link iterate()}.
|
||||
*/
|
||||
protected function _prepare()
|
||||
protected function prepare()
|
||||
{}
|
||||
|
||||
/**
|
||||
* Excutes one-time cleanup tasks at the end of a hydration that was initiated
|
||||
* through {@link hydrateAll} or {@link iterate()}.
|
||||
*/
|
||||
protected function _cleanup()
|
||||
protected function cleanup()
|
||||
{
|
||||
$this->_rsm = null;
|
||||
|
||||
$this->_stmt->closeCursor();
|
||||
$this->_stmt = null;
|
||||
}
|
||||
@@ -146,70 +166,106 @@ abstract class AbstractHydrator
|
||||
* @param array $cache The cache to use.
|
||||
* @param mixed $result The result to fill.
|
||||
*/
|
||||
protected function _hydrateRow(array $data, array &$cache, array &$result)
|
||||
protected function hydrateRowData(array $data, array &$cache, array &$result)
|
||||
{
|
||||
throw new HydrationException("_hydrateRow() not implemented by this hydrator.");
|
||||
throw new HydrationException("hydrateRowData() not implemented by this hydrator.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrates all rows from the current statement instance at once.
|
||||
*/
|
||||
abstract protected function _hydrateAll();
|
||||
abstract protected function hydrateAllData();
|
||||
|
||||
/**
|
||||
* Processes a row of the result set.
|
||||
*
|
||||
* Used for identity-based hydration (HYDRATE_OBJECT and HYDRATE_ARRAY).
|
||||
* Puts the elements of a result row into a new array, grouped by the class
|
||||
* Puts the elements of a result row into a new array, grouped by the dql alias
|
||||
* they belong to. The column names in the result set are mapped to their
|
||||
* field names during this procedure as well as any necessary conversions on
|
||||
* the values applied.
|
||||
* the values applied. Scalar values are kept in a specfic key 'scalars'.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
protected function _gatherRowData(array $data, array &$cache, array &$id, array &$nonemptyComponents)
|
||||
protected function gatherRowData(array $data, array &$cache, array &$id, array &$nonemptyComponents)
|
||||
{
|
||||
$rowData = array();
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
// Parse each column name only once. Cache the results.
|
||||
if ( ! isset($cache[$key])) {
|
||||
if (isset($this->_rsm->scalarMappings[$key])) {
|
||||
$cache[$key]['fieldName'] = $this->_rsm->scalarMappings[$key];
|
||||
$cache[$key]['isScalar'] = true;
|
||||
} else if (isset($this->_rsm->fieldMappings[$key])) {
|
||||
$fieldName = $this->_rsm->fieldMappings[$key];
|
||||
$classMetadata = $this->_em->getClassMetadata($this->_rsm->declaringClasses[$key]);
|
||||
$cache[$key]['fieldName'] = $fieldName;
|
||||
$cache[$key]['type'] = Type::getType($classMetadata->fieldMappings[$fieldName]['type']);
|
||||
$cache[$key]['isIdentifier'] = $classMetadata->isIdentifier($fieldName);
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
} else if (!isset($this->_rsm->metaMappings[$key])) {
|
||||
// this column is a left over, maybe from a LIMIT query hack for example in Oracle or DB2
|
||||
// maybe from an additional column that has not been defined in a NativeQuery ResultSetMapping.
|
||||
continue;
|
||||
} else {
|
||||
// Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns).
|
||||
$cache[$key]['isMetaColumn'] = true;
|
||||
$cache[$key]['fieldName'] = $this->_rsm->metaMappings[$key];
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
switch (true) {
|
||||
// NOTE: Most of the times it's a field mapping, so keep it first!!!
|
||||
case (isset($this->_rsm->fieldMappings[$key])):
|
||||
$fieldName = $this->_rsm->fieldMappings[$key];
|
||||
$classMetadata = $this->_em->getClassMetadata($this->_rsm->declaringClasses[$key]);
|
||||
|
||||
$cache[$key]['fieldName'] = $fieldName;
|
||||
$cache[$key]['type'] = Type::getType($classMetadata->fieldMappings[$fieldName]['type']);
|
||||
$cache[$key]['isIdentifier'] = $classMetadata->isIdentifier($fieldName);
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
break;
|
||||
|
||||
case (isset($this->_rsm->scalarMappings[$key])):
|
||||
$cache[$key]['fieldName'] = $this->_rsm->scalarMappings[$key];
|
||||
$cache[$key]['type'] = Type::getType($this->_rsm->typeMappings[$key]);
|
||||
$cache[$key]['isScalar'] = true;
|
||||
break;
|
||||
|
||||
case (isset($this->_rsm->metaMappings[$key])):
|
||||
// Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns).
|
||||
$fieldName = $this->_rsm->metaMappings[$key];
|
||||
$classMetadata = $this->_em->getClassMetadata($this->_rsm->aliasMap[$this->_rsm->columnOwnerMap[$key]]);
|
||||
|
||||
$cache[$key]['isMetaColumn'] = true;
|
||||
$cache[$key]['fieldName'] = $fieldName;
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
$cache[$key]['isIdentifier'] = isset($this->_rsm->isIdentifierColumn[$cache[$key]['dqlAlias']][$key]);
|
||||
break;
|
||||
|
||||
default:
|
||||
// this column is a left over, maybe from a LIMIT query hack for example in Oracle or DB2
|
||||
// maybe from an additional column that has not been defined in a NativeQuery ResultSetMapping.
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isset($cache[$key]['isScalar'])) {
|
||||
$value = $cache[$key]['type']->convertToPHPValue($value, $this->_platform);
|
||||
|
||||
$rowData['scalars'][$cache[$key]['fieldName']] = $value;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
$dqlAlias = $cache[$key]['dqlAlias'];
|
||||
|
||||
if ($cache[$key]['isIdentifier']) {
|
||||
$id[$dqlAlias] .= '|' . $value;
|
||||
}
|
||||
|
||||
if (isset($cache[$key]['isMetaColumn'])) {
|
||||
$rowData[$dqlAlias][$cache[$key]['fieldName']] = $value;
|
||||
if ( ! isset($rowData[$dqlAlias][$cache[$key]['fieldName']]) && $value !== null) {
|
||||
$rowData[$dqlAlias][$cache[$key]['fieldName']] = $value;
|
||||
if ($cache[$key]['isIdentifier']) {
|
||||
$nonemptyComponents[$dqlAlias] = true;
|
||||
}
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($cache[$key]['isIdentifier']) {
|
||||
$id[$dqlAlias] .= '|' . $value;
|
||||
// in an inheritance hierarchy 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;
|
||||
}
|
||||
|
||||
$rowData[$dqlAlias][$cache[$key]['fieldName']] = $cache[$key]['type']->convertToPHPValue($value, $this->_platform);
|
||||
@@ -224,6 +280,7 @@ abstract class AbstractHydrator
|
||||
|
||||
/**
|
||||
* Processes a row of the result set.
|
||||
*
|
||||
* Used for HYDRATE_SCALAR. This is a variant of _gatherRowData() that
|
||||
* simply converts column names to field names and properly converts the
|
||||
* values according to their types. The resulting row has the same number
|
||||
@@ -231,48 +288,103 @@ abstract class AbstractHydrator
|
||||
*
|
||||
* @param array $data
|
||||
* @param array $cache
|
||||
*
|
||||
* @return array The processed row.
|
||||
*/
|
||||
protected function _gatherScalarRowData(&$data, &$cache)
|
||||
protected function gatherScalarRowData(&$data, &$cache)
|
||||
{
|
||||
$rowData = array();
|
||||
|
||||
foreach ($data as $key => $value) {
|
||||
// Parse each column name only once. Cache the results.
|
||||
if ( ! isset($cache[$key])) {
|
||||
if (isset($this->_rsm->scalarMappings[$key])) {
|
||||
$cache[$key]['fieldName'] = $this->_rsm->scalarMappings[$key];
|
||||
$cache[$key]['isScalar'] = true;
|
||||
} else if (isset($this->_rsm->fieldMappings[$key])) {
|
||||
$fieldName = $this->_rsm->fieldMappings[$key];
|
||||
$classMetadata = $this->_em->getClassMetadata($this->_rsm->declaringClasses[$key]);
|
||||
$cache[$key]['fieldName'] = $fieldName;
|
||||
$cache[$key]['type'] = Type::getType($classMetadata->fieldMappings[$fieldName]['type']);
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
} else if (!isset($this->_rsm->metaMappings[$key])) {
|
||||
// this column is a left over, maybe from a LIMIT query hack for example in Oracle or DB2
|
||||
// maybe from an additional column that has not been defined in a NativeQuery ResultSetMapping.
|
||||
continue;
|
||||
} else {
|
||||
// Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns).
|
||||
$cache[$key]['isMetaColumn'] = true;
|
||||
$cache[$key]['fieldName'] = $this->_rsm->metaMappings[$key];
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
switch (true) {
|
||||
// NOTE: During scalar hydration, most of the times it's a scalar mapping, keep it first!!!
|
||||
case (isset($this->_rsm->scalarMappings[$key])):
|
||||
$cache[$key]['fieldName'] = $this->_rsm->scalarMappings[$key];
|
||||
$cache[$key]['isScalar'] = true;
|
||||
break;
|
||||
|
||||
case (isset($this->_rsm->fieldMappings[$key])):
|
||||
$fieldName = $this->_rsm->fieldMappings[$key];
|
||||
$classMetadata = $this->_em->getClassMetadata($this->_rsm->declaringClasses[$key]);
|
||||
|
||||
$cache[$key]['fieldName'] = $fieldName;
|
||||
$cache[$key]['type'] = Type::getType($classMetadata->fieldMappings[$fieldName]['type']);
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
break;
|
||||
|
||||
case (isset($this->_rsm->metaMappings[$key])):
|
||||
// Meta column (has meaning in relational schema only, i.e. foreign keys or discriminator columns).
|
||||
$cache[$key]['isMetaColumn'] = true;
|
||||
$cache[$key]['fieldName'] = $this->_rsm->metaMappings[$key];
|
||||
$cache[$key]['dqlAlias'] = $this->_rsm->columnOwnerMap[$key];
|
||||
break;
|
||||
|
||||
default:
|
||||
// this column is a left over, maybe from a LIMIT query hack for example in Oracle or DB2
|
||||
// maybe from an additional column that has not been defined in a NativeQuery ResultSetMapping.
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$fieldName = $cache[$key]['fieldName'];
|
||||
|
||||
if (isset($cache[$key]['isScalar'])) {
|
||||
$rowData[$fieldName] = $value;
|
||||
} else if (isset($cache[$key]['isMetaColumn'])) {
|
||||
$rowData[$cache[$key]['dqlAlias'] . '_' . $fieldName] = $value;
|
||||
} else {
|
||||
$rowData[$cache[$key]['dqlAlias'] . '_' . $fieldName] = $cache[$key]['type']
|
||||
->convertToPHPValue($value, $this->_platform);
|
||||
switch (true) {
|
||||
case (isset($cache[$key]['isScalar'])):
|
||||
$rowData[$fieldName] = $value;
|
||||
break;
|
||||
|
||||
case (isset($cache[$key]['isMetaColumn'])):
|
||||
$rowData[$cache[$key]['dqlAlias'] . '_' . $fieldName] = $value;
|
||||
break;
|
||||
|
||||
default:
|
||||
$value = $cache[$key]['type']->convertToPHPValue($value, $this->_platform);
|
||||
|
||||
$rowData[$cache[$key]['dqlAlias'] . '_' . $fieldName] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $rowData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register entity as managed in UnitOfWork.
|
||||
*
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
* @param object $entity
|
||||
* @param array $data
|
||||
*
|
||||
* @todo The "$id" generation is the same of UnitOfWork#createEntity. Remove this duplication somehow
|
||||
*/
|
||||
protected function registerManaged(ClassMetadata $class, $entity, array $data)
|
||||
{
|
||||
if ($class->isIdentifierComposite) {
|
||||
$id = 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* When executed in a hydrate() loop we have to clear internal state to
|
||||
* decrease memory consumption.
|
||||
*/
|
||||
public function onClear($eventArgs)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
@@ -25,8 +25,9 @@ use PDO, Doctrine\DBAL\Connection, Doctrine\ORM\Mapping\ClassMetadata;
|
||||
* The ArrayHydrator produces a nested array "graph" that is often (not always)
|
||||
* interchangeable with the corresponding object graph for read-only access.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 1.0
|
||||
* @author Guilherme Blanco <guilhermeblanoc@hotmail.com>
|
||||
*/
|
||||
class ArrayHydrator extends AbstractHydrator
|
||||
{
|
||||
@@ -38,45 +39,55 @@ class ArrayHydrator extends AbstractHydrator
|
||||
private $_idTemplate = array();
|
||||
private $_resultCounter = 0;
|
||||
|
||||
/** @override */
|
||||
protected function _prepare()
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function prepare()
|
||||
{
|
||||
$this->_isSimpleQuery = count($this->_rsm->aliasMap) <= 1;
|
||||
$this->_identifierMap = array();
|
||||
$this->_isSimpleQuery = count($this->_rsm->aliasMap) <= 1;
|
||||
$this->_identifierMap = array();
|
||||
$this->_resultPointers = array();
|
||||
$this->_idTemplate = array();
|
||||
$this->_resultCounter = 0;
|
||||
$this->_idTemplate = array();
|
||||
$this->_resultCounter = 0;
|
||||
|
||||
foreach ($this->_rsm->aliasMap as $dqlAlias => $className) {
|
||||
$this->_identifierMap[$dqlAlias] = array();
|
||||
$this->_identifierMap[$dqlAlias] = array();
|
||||
$this->_resultPointers[$dqlAlias] = array();
|
||||
$this->_idTemplate[$dqlAlias] = '';
|
||||
$this->_idTemplate[$dqlAlias] = '';
|
||||
}
|
||||
}
|
||||
|
||||
/** @override */
|
||||
protected function _hydrateAll()
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function hydrateAllData()
|
||||
{
|
||||
$result = array();
|
||||
$cache = array();
|
||||
$cache = array();
|
||||
|
||||
while ($data = $this->_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$this->_hydrateRow($data, $cache, $result);
|
||||
$this->hydrateRowData($data, $cache, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/** @override */
|
||||
protected function _hydrateRow(array $data, array &$cache, array &$result)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function hydrateRowData(array $row, array &$cache, array &$result)
|
||||
{
|
||||
// 1) Initialize
|
||||
$id = $this->_idTemplate; // initialize the id-memory
|
||||
$nonemptyComponents = array();
|
||||
$rowData = $this->_gatherRowData($data, $cache, $id, $nonemptyComponents);
|
||||
$rowData = $this->gatherRowData($row, $cache, $id, $nonemptyComponents);
|
||||
|
||||
// Extract scalar values. They're appended at the end.
|
||||
if (isset($rowData['scalars'])) {
|
||||
$scalars = $rowData['scalars'];
|
||||
|
||||
unset($rowData['scalars']);
|
||||
|
||||
if (empty($rowData)) {
|
||||
++$this->_resultCounter;
|
||||
}
|
||||
@@ -90,12 +101,17 @@ class ArrayHydrator extends AbstractHydrator
|
||||
// It's a joined result
|
||||
|
||||
$parent = $this->_rsm->parentAliasMap[$dqlAlias];
|
||||
$path = $parent . '.' . $dqlAlias;
|
||||
$path = $parent . '.' . $dqlAlias;
|
||||
|
||||
// missing parent data, skipping as RIGHT JOIN hydration is not supported.
|
||||
if ( ! isset($nonemptyComponents[$parent]) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get a reference to the right element in the result tree.
|
||||
// This element will get the associated element attached.
|
||||
if ($this->_rsm->isMixed && isset($this->_rootAliases[$parent])) {
|
||||
$first = reset($this->_resultPointers);
|
||||
$first = reset($this->_resultPointers);
|
||||
// TODO: Exception if $key === null ?
|
||||
$baseElement =& $this->_resultPointers[$parent][key($first)];
|
||||
} else if (isset($this->_resultPointers[$parent])) {
|
||||
@@ -104,39 +120,41 @@ class ArrayHydrator extends AbstractHydrator
|
||||
unset($this->_resultPointers[$dqlAlias]); // Ticket #1228
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
$relationAlias = $this->_rsm->relationMap[$dqlAlias];
|
||||
$relation = $this->_getClassMetadata($this->_rsm->aliasMap[$parent])->associationMappings[$relationAlias];
|
||||
$relation = $this->getClassMetadata($this->_rsm->aliasMap[$parent])->associationMappings[$relationAlias];
|
||||
|
||||
// Check the type of the relation (many or single-valued)
|
||||
if ( ! ($relation['type'] & ClassMetadata::TO_ONE)) {
|
||||
$oneToOne = false;
|
||||
|
||||
if (isset($nonemptyComponents[$dqlAlias])) {
|
||||
if ( ! isset($baseElement[$relationAlias])) {
|
||||
$baseElement[$relationAlias] = array();
|
||||
}
|
||||
|
||||
$indexExists = isset($this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]]);
|
||||
$index = $indexExists ? $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false;
|
||||
|
||||
$indexExists = isset($this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]]);
|
||||
$index = $indexExists ? $this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] : false;
|
||||
$indexIsValid = $index !== false ? isset($baseElement[$relationAlias][$index]) : false;
|
||||
|
||||
|
||||
if ( ! $indexExists || ! $indexIsValid) {
|
||||
$element = $data;
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$field = $this->_rsm->indexByMap[$dqlAlias];
|
||||
$baseElement[$relationAlias][$element[$field]] = $element;
|
||||
$baseElement[$relationAlias][$row[$this->_rsm->indexByMap[$dqlAlias]]] = $element;
|
||||
} else {
|
||||
$baseElement[$relationAlias][] = $element;
|
||||
}
|
||||
|
||||
end($baseElement[$relationAlias]);
|
||||
$this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] =
|
||||
key($baseElement[$relationAlias]);
|
||||
|
||||
$this->_identifierMap[$path][$id[$parent]][$id[$dqlAlias]] = key($baseElement[$relationAlias]);
|
||||
}
|
||||
} else if ( ! isset($baseElement[$relationAlias])) {
|
||||
$baseElement[$relationAlias] = array();
|
||||
}
|
||||
} else {
|
||||
$oneToOne = true;
|
||||
|
||||
if ( ! isset($nonemptyComponents[$dqlAlias]) && ! isset($baseElement[$relationAlias])) {
|
||||
$baseElement[$relationAlias] = null;
|
||||
} else if ( ! isset($baseElement[$relationAlias])) {
|
||||
@@ -152,32 +170,42 @@ class ArrayHydrator extends AbstractHydrator
|
||||
|
||||
} else {
|
||||
// It's a root result element
|
||||
|
||||
|
||||
$this->_rootAliases[$dqlAlias] = true; // Mark as root
|
||||
|
||||
$entityKey = $this->_rsm->entityMappings[$dqlAlias] ?: 0;
|
||||
|
||||
// if this row has a NULL value for the root result id then make it a null result.
|
||||
if ( ! isset($nonemptyComponents[$dqlAlias]) ) {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$result[] = array($entityKey => null);
|
||||
} else {
|
||||
$result[] = null;
|
||||
}
|
||||
$resultKey = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for an existing element
|
||||
if ($this->_isSimpleQuery || ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
|
||||
$element = $rowData[$dqlAlias];
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$field = $this->_rsm->indexByMap[$dqlAlias];
|
||||
if ($this->_rsm->isMixed) {
|
||||
$result[] = array($element[$field] => $element);
|
||||
++$this->_resultCounter;
|
||||
} else {
|
||||
$result[$element[$field]] = $element;
|
||||
}
|
||||
} else {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$result[] = array($element);
|
||||
++$this->_resultCounter;
|
||||
} else {
|
||||
$result[] = $element;
|
||||
}
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array($entityKey => $element);
|
||||
}
|
||||
end($result);
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = key($result);
|
||||
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]];
|
||||
$result[$resultKey] = $element;
|
||||
} else {
|
||||
$resultKey = $this->_resultCounter;
|
||||
$result[] = $element;
|
||||
++$this->_resultCounter;
|
||||
}
|
||||
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $resultKey;
|
||||
} else {
|
||||
$index = $this->_identifierMap[$dqlAlias][$id[$dqlAlias]];
|
||||
$resultKey = $index;
|
||||
/*if ($this->_rsm->isMixed) {
|
||||
$result[] =& $result[$index];
|
||||
++$this->_resultCounter;
|
||||
@@ -189,8 +217,17 @@ class ArrayHydrator extends AbstractHydrator
|
||||
|
||||
// Append scalar values to mixed result sets
|
||||
if (isset($scalars)) {
|
||||
if ( ! isset($resultKey) ) {
|
||||
// this only ever happens when no object is fetched (scalar result only)
|
||||
if (isset($this->_rsm->indexByMap['scalars'])) {
|
||||
$resultKey = $row[$this->_rsm->indexByMap['scalars']];
|
||||
} else {
|
||||
$resultKey = $this->_resultCounter - 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($scalars as $name => $value) {
|
||||
$result[$this->_resultCounter - 1][$name] = $value;
|
||||
$result[$resultKey][$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -208,28 +245,45 @@ class ArrayHydrator extends AbstractHydrator
|
||||
{
|
||||
if ($coll === null) {
|
||||
unset($this->_resultPointers[$dqlAlias]); // Ticket #1228
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($index !== false) {
|
||||
$this->_resultPointers[$dqlAlias] =& $coll[$index];
|
||||
|
||||
return;
|
||||
} else {
|
||||
if ($coll) {
|
||||
if ($oneToOne) {
|
||||
$this->_resultPointers[$dqlAlias] =& $coll;
|
||||
} else {
|
||||
end($coll);
|
||||
$this->_resultPointers[$dqlAlias] =& $coll[key($coll)];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! $coll) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($oneToOne) {
|
||||
$this->_resultPointers[$dqlAlias] =& $coll;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
end($coll);
|
||||
$this->_resultPointers[$dqlAlias] =& $coll[key($coll)];
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
private function _getClassMetadata($className)
|
||||
|
||||
/**
|
||||
* Retrieve ClassMetadata associated to entity class name.
|
||||
*
|
||||
* @param string $className
|
||||
*
|
||||
* @return \Doctrine\ORM\Mapping\ClassMetadata
|
||||
*/
|
||||
private function getClassMetadata($className)
|
||||
{
|
||||
if ( ! isset($this->_ce[$className])) {
|
||||
$this->_ce[$className] = $this->_em->getClassMetadata($className);
|
||||
}
|
||||
|
||||
return $this->_ce[$className];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,10 +8,49 @@ class HydrationException extends \Doctrine\ORM\ORMException
|
||||
{
|
||||
return new self("The result returned by the query was not unique.");
|
||||
}
|
||||
|
||||
|
||||
public static function parentObjectOfRelationNotFound($alias, $parentAlias)
|
||||
{
|
||||
return new self("The parent object of entity result with alias '$alias' was not found."
|
||||
. " The parent alias is '$parentAlias'.");
|
||||
}
|
||||
|
||||
public static function emptyDiscriminatorValue($dqlAlias)
|
||||
{
|
||||
return new self("The DQL alias '" . $dqlAlias . "' contains an entity ".
|
||||
"of an inheritance hierachy with an empty discriminator value. This means " .
|
||||
"that the database contains inconsistent data with an empty " .
|
||||
"discriminator value in a table row."
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3
|
||||
* @param string $entityName
|
||||
* @param string $discrColumnName
|
||||
* @param string $dqlAlias
|
||||
* @return HydrationException
|
||||
*/
|
||||
public static function missingDiscriminatorColumn($entityName, $discrColumnName, $dqlAlias)
|
||||
{
|
||||
return new self(sprintf(
|
||||
'The discriminator column "%s" is missing for "%s" using the DQL alias "%s".',
|
||||
$discrColumnName, $entityName, $dqlAlias
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.3
|
||||
* @param string $entityName
|
||||
* @param string $discrColumnName
|
||||
* @param string $dqlAlias
|
||||
* @return HydrationException
|
||||
*/
|
||||
public static function missingDiscriminatorMetaMappingColumn($entityName, $discrColumnName, $dqlAlias)
|
||||
{
|
||||
return new self(sprintf(
|
||||
'The meta mapping for the discriminator column "%s" is missing for "%s" using the DQL alias "%s".',
|
||||
$discrColumnName, $entityName, $dqlAlias
|
||||
));
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
@@ -101,4 +101,4 @@ class IterableResult implements \Iterator
|
||||
{
|
||||
return ($this->_current!=false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
@@ -23,14 +23,19 @@ use PDO,
|
||||
Doctrine\ORM\Mapping\ClassMetadata,
|
||||
Doctrine\ORM\PersistentCollection,
|
||||
Doctrine\ORM\Query,
|
||||
Doctrine\ORM\Event\LifecycleEventArgs,
|
||||
Doctrine\ORM\Events,
|
||||
Doctrine\Common\Collections\ArrayCollection,
|
||||
Doctrine\Common\Collections\Collection;
|
||||
Doctrine\Common\Collections\Collection,
|
||||
Doctrine\ORM\Proxy\Proxy;
|
||||
|
||||
/**
|
||||
* The ObjectHydrator constructs an object graph out of an SQL result set.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
* @author Guilherme Blanco <guilhermeblanoc@hotmail.com>
|
||||
*
|
||||
* @internal Highly performance-sensitive code.
|
||||
*/
|
||||
class ObjectHydrator extends AbstractHydrator
|
||||
@@ -39,9 +44,9 @@ class ObjectHydrator extends AbstractHydrator
|
||||
* This local cache is maintained between hydration runs and not cleared.
|
||||
*/
|
||||
private $_ce = array();
|
||||
|
||||
|
||||
/* The following parts are reinitialized on every hydration run. */
|
||||
|
||||
|
||||
private $_identifierMap;
|
||||
private $_resultPointers;
|
||||
private $_idTemplate;
|
||||
@@ -49,56 +54,66 @@ class ObjectHydrator extends AbstractHydrator
|
||||
private $_rootAliases = array();
|
||||
private $_initializedCollections = array();
|
||||
private $_existingCollections = array();
|
||||
//private $_createdEntities;
|
||||
|
||||
|
||||
|
||||
/** @override */
|
||||
protected function _prepare()
|
||||
protected function prepare()
|
||||
{
|
||||
$this->_identifierMap =
|
||||
$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();
|
||||
$this->_idTemplate[$dqlAlias] = '';
|
||||
$class = $this->_em->getClassMetadata($className);
|
||||
$this->_idTemplate[$dqlAlias] = '';
|
||||
|
||||
if ( ! isset($this->_ce[$className])) {
|
||||
$this->_ce[$className] = $class;
|
||||
$this->_ce[$className] = $this->_em->getClassMetadata($className);
|
||||
}
|
||||
|
||||
|
||||
// Remember which associations are "fetch joined", so that we know where to inject
|
||||
// collection stubs or proxies and where not.
|
||||
if (isset($this->_rsm->relationMap[$dqlAlias])) {
|
||||
$sourceClassName = $this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]];
|
||||
$sourceClass = $this->_getClassMetadata($sourceClassName);
|
||||
$assoc = $sourceClass->associationMappings[$this->_rsm->relationMap[$dqlAlias]];
|
||||
$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'][$className][$assoc['mappedBy']] = true;
|
||||
} else {
|
||||
if ($assoc['inversedBy']) {
|
||||
$inverseAssoc = $class->associationMappings[$assoc['inversedBy']];
|
||||
if ($inverseAssoc['type'] & ClassMetadata::TO_ONE) {
|
||||
$this->_hints['fetched'][$className][$inverseAssoc['fieldName']] = true;
|
||||
if ($class->subClasses) {
|
||||
foreach ($class->subClasses as $targetSubclassName) {
|
||||
$this->_hints['fetched'][$targetSubclassName][$inverseAssoc['fieldName']] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ( ! isset($this->_rsm->relationMap[$dqlAlias])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( ! isset($this->_rsm->aliasMap[$this->_rsm->parentAliasMap[$dqlAlias]])) {
|
||||
throw HydrationException::parentObjectOfRelationNotFound($dqlAlias, $this->_rsm->parentAliasMap[$dqlAlias]);
|
||||
}
|
||||
|
||||
$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;
|
||||
|
||||
if ($assoc['type'] === ClassMetadata::MANY_TO_MANY) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Mark any non-collection opposite sides as fetched, too.
|
||||
if ($assoc['mappedBy']) {
|
||||
$this->_hints['fetched'][$dqlAlias][$assoc['mappedBy']] = true;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// handle fetch-joined owning side bi-directional one-to-one associations
|
||||
if ($assoc['inversedBy']) {
|
||||
$class = $this->_ce[$className];
|
||||
$inverseAssoc = $class->associationMappings[$assoc['inversedBy']];
|
||||
|
||||
if ( ! ($inverseAssoc['type'] & ClassMetadata::TO_ONE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->_hints['fetched'][$dqlAlias][$inverseAssoc['fieldName']] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,25 +121,32 @@ class ObjectHydrator extends AbstractHydrator
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _cleanup()
|
||||
protected function cleanup()
|
||||
{
|
||||
parent::_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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _hydrateAll()
|
||||
protected function hydrateAllData()
|
||||
{
|
||||
$result = array();
|
||||
$cache = array();
|
||||
$cache = array();
|
||||
|
||||
while ($row = $this->_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$this->_hydrateRow($row, $cache, $result);
|
||||
$this->hydrateRowData($row, $cache, $result);
|
||||
}
|
||||
|
||||
// Take snapshots from all newly initialized collections
|
||||
@@ -138,36 +160,41 @@ class ObjectHydrator extends AbstractHydrator
|
||||
/**
|
||||
* Initializes a related collection.
|
||||
*
|
||||
* @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.
|
||||
* @param object $entity The entity to which the collection belongs.
|
||||
* @param ClassMetadata $class
|
||||
* @param string $fieldName The name of the field on the entity that holds the collection.
|
||||
* @param string $parentDqlAlias Alias of the parent fetch joining this collection.
|
||||
*/
|
||||
private function _initRelatedCollection($entity, $class, $fieldName)
|
||||
private function _initRelatedCollection($entity, $class, $fieldName, $parentDqlAlias)
|
||||
{
|
||||
$oid = spl_object_hash($entity);
|
||||
$oid = spl_object_hash($entity);
|
||||
$relation = $class->associationMappings[$fieldName];
|
||||
$value = $class->reflFields[$fieldName]->getValue($entity);
|
||||
|
||||
$value = $class->reflFields[$fieldName]->getValue($entity);
|
||||
if ($value === null) {
|
||||
$value = new ArrayCollection;
|
||||
}
|
||||
|
||||
if ( ! $value instanceof PersistentCollection) {
|
||||
$value = new PersistentCollection(
|
||||
$this->_em,
|
||||
$this->_ce[$relation['targetEntity']],
|
||||
$value
|
||||
$this->_em, $this->_ce[$relation['targetEntity']], $value
|
||||
);
|
||||
$value->setOwner($entity, $relation);
|
||||
|
||||
$class->reflFields[$fieldName]->setValue($entity, $value);
|
||||
$this->_uow->setOriginalEntityProperty($oid, $fieldName, $value);
|
||||
|
||||
$this->_initializedCollections[$oid . $fieldName] = $value;
|
||||
} else if (isset($this->_hints[Query::HINT_REFRESH]) ||
|
||||
isset($this->_hints['fetched'][$class->name][$fieldName]) &&
|
||||
! $value->isInitialized()) {
|
||||
} else if (
|
||||
isset($this->_hints[Query::HINT_REFRESH]) ||
|
||||
isset($this->_hints['fetched'][$parentDqlAlias][$fieldName]) &&
|
||||
! $value->isInitialized()
|
||||
) {
|
||||
// Is already PersistentCollection, but either REFRESH or FETCH-JOIN and UNINITIALIZED!
|
||||
$value->setDirty(false);
|
||||
$value->setInitialized(true);
|
||||
$value->unwrap()->clear();
|
||||
|
||||
$this->_initializedCollections[$oid . $fieldName] = $value;
|
||||
} else {
|
||||
// Is already PersistentCollection, and DON'T REFRESH or FETCH-JOIN!
|
||||
@@ -176,44 +203,81 @@ class ObjectHydrator extends AbstractHydrator
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets an entity instance.
|
||||
*
|
||||
* @param $data The instance data.
|
||||
* @param $dqlAlias The DQL alias of the entity's class.
|
||||
*
|
||||
* @param array $data The instance data.
|
||||
* @param string $dqlAlias The DQL alias of the entity's class.
|
||||
* @return object The entity.
|
||||
*/
|
||||
private function _getEntity(array $data, $dqlAlias)
|
||||
{
|
||||
$className = $this->_rsm->aliasMap[$dqlAlias];
|
||||
$className = $this->_rsm->aliasMap[$dqlAlias];
|
||||
|
||||
if (isset($this->_rsm->discriminatorColumns[$dqlAlias])) {
|
||||
|
||||
if ( ! isset($this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]])) {
|
||||
throw HydrationException::missingDiscriminatorMetaMappingColumn($className, $this->_rsm->discriminatorColumns[$dqlAlias], $dqlAlias);
|
||||
}
|
||||
|
||||
$discrColumn = $this->_rsm->metaMappings[$this->_rsm->discriminatorColumns[$dqlAlias]];
|
||||
|
||||
if ( ! isset($data[$discrColumn])) {
|
||||
throw HydrationException::missingDiscriminatorColumn($className, $discrColumn, $dqlAlias);
|
||||
}
|
||||
|
||||
if ($data[$discrColumn] === "") {
|
||||
throw HydrationException::emptyDiscriminatorValue($dqlAlias);
|
||||
}
|
||||
|
||||
$className = $this->_ce[$className]->discriminatorMap[$data[$discrColumn]];
|
||||
|
||||
unset($data[$discrColumn]);
|
||||
}
|
||||
|
||||
if (isset($this->_hints[Query::HINT_REFRESH_ENTITY]) && isset($this->_rootAliases[$dqlAlias])) {
|
||||
$this->registerManaged($this->_ce[$className], $this->_hints[Query::HINT_REFRESH_ENTITY], $data);
|
||||
}
|
||||
|
||||
$this->_hints['fetchAlias'] = $dqlAlias;
|
||||
|
||||
return $this->_uow->createEntity($className, $data, $this->_hints);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @param array $data
|
||||
* @return mixed
|
||||
*/
|
||||
private function _getEntityFromIdentityMap($className, array $data)
|
||||
{
|
||||
// TODO: Abstract this code and UnitOfWork::createEntity() equivalent?
|
||||
$class = $this->_ce[$className];
|
||||
|
||||
/* @var $class ClassMetadata */
|
||||
if ($class->isIdentifierComposite) {
|
||||
$idHash = '';
|
||||
foreach ($class->identifier as $fieldName) {
|
||||
$idHash .= $data[$fieldName] . ' ';
|
||||
if (isset($class->associationMappings[$fieldName])) {
|
||||
$idHash .= $data[$class->associationMappings[$fieldName]['joinColumns'][0]['name']] . ' ';
|
||||
} else {
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
@@ -222,42 +286,45 @@ class ObjectHydrator extends AbstractHydrator
|
||||
if ( ! isset($this->_ce[$className])) {
|
||||
$this->_ce[$className] = $this->_em->getClassMetadata($className);
|
||||
}
|
||||
|
||||
return $this->_ce[$className];
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrates a single row in an SQL result set.
|
||||
*
|
||||
*
|
||||
* @internal
|
||||
* First, the data of the row is split into chunks where each chunk contains data
|
||||
* that belongs to a particular component/class. Afterwards, all these chunks
|
||||
* are processed, one after the other. For each chunk of class data only one of the
|
||||
* following code paths is executed:
|
||||
*
|
||||
*
|
||||
* Path A: The data chunk belongs to a joined/associated object and the association
|
||||
* is collection-valued.
|
||||
* Path B: The data chunk belongs to a joined/associated object and the association
|
||||
* is single-valued.
|
||||
* Path C: The data chunk belongs to a root result element/object that appears in the topmost
|
||||
* level of the hydrated result. A typical example are the objects of the type
|
||||
* specified by the FROM clause in a DQL query.
|
||||
*
|
||||
* @param array $data The data of the row to process.
|
||||
* @param array $cache The cache to use.
|
||||
* specified by the FROM clause in a DQL query.
|
||||
*
|
||||
* @param array $row The data of the row to process.
|
||||
* @param array $cache The cache to use.
|
||||
* @param array $result The result array to fill.
|
||||
*/
|
||||
protected function _hydrateRow(array $data, array &$cache, array &$result)
|
||||
protected function hydrateRowData(array $row, array &$cache, array &$result)
|
||||
{
|
||||
// Initialize
|
||||
$id = $this->_idTemplate; // initialize the id-memory
|
||||
$nonemptyComponents = array();
|
||||
// Split the row data into chunks of class data.
|
||||
$rowData = $this->_gatherRowData($data, $cache, $id, $nonemptyComponents);
|
||||
$rowData = $this->gatherRowData($row, $cache, $id, $nonemptyComponents);
|
||||
|
||||
// Extract scalar values. They're appended at the end.
|
||||
if (isset($rowData['scalars'])) {
|
||||
$scalars = $rowData['scalars'];
|
||||
|
||||
unset($rowData['scalars']);
|
||||
|
||||
if (empty($rowData)) {
|
||||
++$this->_resultCounter;
|
||||
}
|
||||
@@ -266,7 +333,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
// Hydrate the data chunks
|
||||
foreach ($rowData as $dqlAlias => $data) {
|
||||
$entityName = $this->_rsm->aliasMap[$dqlAlias];
|
||||
|
||||
|
||||
if (isset($this->_rsm->parentAliasMap[$dqlAlias])) {
|
||||
// It's a joined result
|
||||
|
||||
@@ -275,10 +342,16 @@ 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 = $this->_resultPointers[$parentAlias][key($first)];
|
||||
$first = reset($this->_resultPointers);
|
||||
$parentObject = $first[key($first)];
|
||||
} else if (isset($this->_resultPointers[$parentAlias])) {
|
||||
$parentObject = $this->_resultPointers[$parentAlias];
|
||||
} else {
|
||||
@@ -294,19 +367,20 @@ class ObjectHydrator extends AbstractHydrator
|
||||
|
||||
// Check the type of the relation (many or single-valued)
|
||||
if ( ! ($relation['type'] & ClassMetadata::TO_ONE)) {
|
||||
$reflFieldValue = $reflField->getValue($parentObject);
|
||||
// PATH A: Collection-valued association
|
||||
if (isset($nonemptyComponents[$dqlAlias])) {
|
||||
$collKey = $oid . $relationField;
|
||||
if (isset($this->_initializedCollections[$collKey])) {
|
||||
$reflFieldValue = $this->_initializedCollections[$collKey];
|
||||
} else if ( ! isset($this->_existingCollections[$collKey])) {
|
||||
$reflFieldValue = $this->_initRelatedCollection($parentObject, $parentClass, $relationField);
|
||||
$reflFieldValue = $this->_initRelatedCollection($parentObject, $parentClass, $relationField, $parentAlias);
|
||||
}
|
||||
|
||||
|
||||
$indexExists = isset($this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]]);
|
||||
$index = $indexExists ? $this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] : false;
|
||||
$indexIsValid = $index !== false ? isset($reflFieldValue[$index]) : false;
|
||||
|
||||
|
||||
if ( ! $indexExists || ! $indexIsValid) {
|
||||
if (isset($this->_existingCollections[$collKey])) {
|
||||
// Collection exists, only look for the element in the identity map.
|
||||
@@ -319,8 +393,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
$element = $this->_getEntity($data, $dqlAlias);
|
||||
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$field = $this->_rsm->indexByMap[$dqlAlias];
|
||||
$indexValue = $this->_ce[$entityName]->reflFields[$field]->getValue($element);
|
||||
$indexValue = $row[$this->_rsm->indexByMap[$dqlAlias]];
|
||||
$reflFieldValue->hydrateSet($indexValue, $element);
|
||||
$this->_identifierMap[$path][$id[$parentAlias]][$id[$dqlAlias]] = $indexValue;
|
||||
} else {
|
||||
@@ -335,21 +408,24 @@ class ObjectHydrator extends AbstractHydrator
|
||||
// Update result pointer
|
||||
$this->_resultPointers[$dqlAlias] = $reflFieldValue[$index];
|
||||
}
|
||||
} else if ( ! $reflField->getValue($parentObject)) {
|
||||
$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 if ( ! $reflFieldValue) {
|
||||
$reflFieldValue = $this->_initRelatedCollection($parentObject, $parentClass, $relationField, $parentAlias);
|
||||
} else if ($reflFieldValue instanceof PersistentCollection && $reflFieldValue->isInitialized() === false) {
|
||||
$reflFieldValue->setInitialized(true);
|
||||
}
|
||||
|
||||
} else {
|
||||
// PATH B: Single-valued association
|
||||
$reflFieldValue = $reflField->getValue($parentObject);
|
||||
if ( ! $reflFieldValue || isset($this->_hints[Query::HINT_REFRESH])) {
|
||||
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 (isset($nonemptyComponents[$dqlAlias])) {
|
||||
$element = $this->_getEntity($data, $dqlAlias);
|
||||
$reflField->setValue($parentObject, $element);
|
||||
$this->_uow->setOriginalEntityProperty($oid, $relationField, $element);
|
||||
$targetClass = $this->_ce[$relation['targetEntity']];
|
||||
|
||||
if ($relation['isOwningSide']) {
|
||||
//TODO: Just check hints['fetched'] here?
|
||||
// If there is an inverse mapping on the target class its bidirectional
|
||||
@@ -370,6 +446,9 @@ class ObjectHydrator extends AbstractHydrator
|
||||
}
|
||||
// Update result pointer
|
||||
$this->_resultPointers[$dqlAlias] = $element;
|
||||
} else {
|
||||
$this->_uow->setOriginalEntityProperty($oid, $relationField, null);
|
||||
$reflField->setValue($parentObject, null);
|
||||
}
|
||||
// else leave $reflFieldValue null for single-valued associations
|
||||
} else {
|
||||
@@ -380,30 +459,48 @@ class ObjectHydrator extends AbstractHydrator
|
||||
} else {
|
||||
// PATH C: Its a root result element
|
||||
$this->_rootAliases[$dqlAlias] = true; // Mark as root alias
|
||||
$entityKey = $this->_rsm->entityMappings[$dqlAlias] ?: 0;
|
||||
|
||||
// if this row has a NULL value for the root result id then make it a null result.
|
||||
if ( ! isset($nonemptyComponents[$dqlAlias]) ) {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$result[] = array($entityKey => null);
|
||||
} else {
|
||||
$result[] = null;
|
||||
}
|
||||
$resultKey = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
continue;
|
||||
}
|
||||
|
||||
// check for existing result from the iterations before
|
||||
if ( ! isset($this->_identifierMap[$dqlAlias][$id[$dqlAlias]])) {
|
||||
$element = $this->_getEntity($rowData[$dqlAlias], $dqlAlias);
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$field = $this->_rsm->indexByMap[$dqlAlias];
|
||||
$key = $this->_ce[$entityName]->reflFields[$field]->getValue($element);
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array($key => $element);
|
||||
$result[] = $element;
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
} else {
|
||||
$result[$key] = $element;
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $key;
|
||||
}
|
||||
} else {
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array(0 => $element);
|
||||
}
|
||||
$result[] = $element;
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
if ($this->_rsm->isMixed) {
|
||||
$element = array($entityKey => $element);
|
||||
}
|
||||
|
||||
if (isset($this->_rsm->indexByMap[$dqlAlias])) {
|
||||
$resultKey = $row[$this->_rsm->indexByMap[$dqlAlias]];
|
||||
|
||||
if (isset($this->_hints['collection'])) {
|
||||
$this->_hints['collection']->hydrateSet($resultKey, $element);
|
||||
}
|
||||
|
||||
$result[$resultKey] = $element;
|
||||
} else {
|
||||
$resultKey = $this->_resultCounter;
|
||||
++$this->_resultCounter;
|
||||
|
||||
if (isset($this->_hints['collection'])) {
|
||||
$this->_hints['collection']->hydrateAdd($element);
|
||||
}
|
||||
|
||||
$result[] = $element;
|
||||
}
|
||||
|
||||
$this->_identifierMap[$dqlAlias][$id[$dqlAlias]] = $resultKey;
|
||||
|
||||
// Update result pointer
|
||||
$this->_resultPointers[$dqlAlias] = $element;
|
||||
|
||||
@@ -411,6 +508,7 @@ class ObjectHydrator extends AbstractHydrator
|
||||
// Update result pointer
|
||||
$index = $this->_identifierMap[$dqlAlias][$id[$dqlAlias]];
|
||||
$this->_resultPointers[$dqlAlias] = $result[$index];
|
||||
$resultKey = $index;
|
||||
/*if ($this->_rsm->isMixed) {
|
||||
$result[] = $result[$index];
|
||||
++$this->_resultCounter;
|
||||
@@ -421,9 +519,33 @@ class ObjectHydrator extends AbstractHydrator
|
||||
|
||||
// Append scalar values to mixed result sets
|
||||
if (isset($scalars)) {
|
||||
if ( ! isset($resultKey) ) {
|
||||
if (isset($this->_rsm->indexByMap['scalars'])) {
|
||||
$resultKey = $row[$this->_rsm->indexByMap['scalars']];
|
||||
} else {
|
||||
$resultKey = $this->_resultCounter - 1;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($scalars as $name => $value) {
|
||||
$result[$this->_resultCounter - 1][$name] = $value;
|
||||
$result[$resultKey][$name] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When executed in a hydrate() loop we may have to clear internal state to
|
||||
* decrease memory consumption.
|
||||
*/
|
||||
public function onClear($eventArgs)
|
||||
{
|
||||
parent::onClear($eventArgs);
|
||||
|
||||
$aliases = array_keys($this->_identifierMap);
|
||||
$this->_identifierMap = array();
|
||||
|
||||
foreach ($aliases as $alias) {
|
||||
$this->_identifierMap[$alias] = array();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,38 +13,43 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Internal\Hydration;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
|
||||
/**
|
||||
* Hydrator that produces flat, rectangular results of scalar data.
|
||||
* The created result is almost the same as a regular SQL result set, except
|
||||
* that column names are mapped to field names and data type conversions take place.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
*/
|
||||
class ScalarHydrator extends AbstractHydrator
|
||||
{
|
||||
/** @override */
|
||||
protected function _hydrateAll()
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function hydrateAllData()
|
||||
{
|
||||
$result = array();
|
||||
$cache = array();
|
||||
$cache = array();
|
||||
|
||||
while ($data = $this->_stmt->fetch(\PDO::FETCH_ASSOC)) {
|
||||
$result[] = $this->_gatherScalarRowData($data, $cache);
|
||||
$this->hydrateRowData($data, $cache, $result);
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/** @override */
|
||||
protected function _hydrateRow(array $data, array &$cache, array &$result)
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function hydrateRowData(array $data, array &$cache, array &$result)
|
||||
{
|
||||
$result[] = $this->_gatherScalarRowData($data, $cache);
|
||||
$result[] = $this->gatherScalarRowData($data, $cache);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
187
lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php
Normal file
187
lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php
Normal file
@@ -0,0 +1,187 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Internal\Hydration;
|
||||
|
||||
use \PDO,
|
||||
Doctrine\DBAL\Types\Type,
|
||||
Doctrine\ORM\Mapping\ClassMetadata,
|
||||
Doctrine\ORM\Event\LifecycleEventArgs,
|
||||
Doctrine\ORM\Events,
|
||||
Doctrine\ORM\Query;
|
||||
|
||||
class SimpleObjectHydrator extends AbstractHydrator
|
||||
{
|
||||
/**
|
||||
* @var ClassMetadata
|
||||
*/
|
||||
private $class;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $declaringClasses = array();
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function hydrateAllData()
|
||||
{
|
||||
$result = array();
|
||||
$cache = array();
|
||||
|
||||
while ($row = $this->_stmt->fetch(PDO::FETCH_ASSOC)) {
|
||||
$this->hydrateRowData($row, $cache, $result);
|
||||
}
|
||||
|
||||
$this->_em->getUnitOfWork()->triggerEagerLoads();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function prepare()
|
||||
{
|
||||
if (count($this->_rsm->aliasMap) !== 1) {
|
||||
throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping that contains more than one object result.");
|
||||
}
|
||||
|
||||
if ($this->_rsm->scalarMappings) {
|
||||
throw new \RuntimeException("Cannot use SimpleObjectHydrator with a ResultSetMapping that contains scalar mappings.");
|
||||
}
|
||||
|
||||
$this->class = $this->_em->getClassMetadata(reset($this->_rsm->aliasMap));
|
||||
|
||||
// We only need to add declaring classes if we have inheritance.
|
||||
if ($this->class->inheritanceType === ClassMetadata::INHERITANCE_TYPE_NONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
foreach ($this->_rsm->declaringClasses as $column => $class) {
|
||||
$this->declaringClasses[$column] = $this->_em->getClassMetadata($class);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function hydrateRowData(array $sqlResult, array &$cache, array &$result)
|
||||
{
|
||||
$entityName = $this->class->name;
|
||||
$data = array();
|
||||
|
||||
// We need to find the correct entity class name if we have inheritance in resultset
|
||||
if ($this->class->inheritanceType !== ClassMetadata::INHERITANCE_TYPE_NONE) {
|
||||
$discrColumnName = $this->_platform->getSQLResultCasing($this->class->discriminatorColumn['name']);
|
||||
|
||||
if ( ! isset($sqlResult[$discrColumnName])) {
|
||||
throw HydrationException::missingDiscriminatorColumn($entityName, $discrColumnName, key($this->_rsm->aliasMap));
|
||||
}
|
||||
|
||||
if ($sqlResult[$discrColumnName] === '') {
|
||||
throw HydrationException::emptyDiscriminatorValue(key($this->_rsm->aliasMap));
|
||||
}
|
||||
|
||||
$entityName = $this->class->discriminatorMap[$sqlResult[$discrColumnName]];
|
||||
|
||||
unset($sqlResult[$discrColumnName]);
|
||||
}
|
||||
|
||||
foreach ($sqlResult as $column => $value) {
|
||||
// Hydrate column information if not yet present
|
||||
if ( ! isset($cache[$column])) {
|
||||
if (($info = $this->hydrateColumnInfo($entityName, $column)) === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$cache[$column] = $info;
|
||||
}
|
||||
|
||||
// Convert field to a valid PHP value
|
||||
if (isset($cache[$column]['field'])) {
|
||||
$type = Type::getType($cache[$column]['class']->fieldMappings[$cache[$column]['name']]['type']);
|
||||
$value = $type->convertToPHPValue($value, $this->_platform);
|
||||
}
|
||||
|
||||
// Prevent overwrite in case of inherit classes using 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);
|
||||
}
|
||||
|
||||
$uow = $this->_em->getUnitOfWork();
|
||||
$entity = $uow->createEntity($entityName, $data, $this->_hints);
|
||||
|
||||
$result[] = $entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve column information form ResultSetMapping.
|
||||
*
|
||||
* @param string $entityName
|
||||
* @param string $column
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function hydrateColumnInfo($entityName, $column)
|
||||
{
|
||||
switch (true) {
|
||||
case (isset($this->_rsm->fieldMappings[$column])):
|
||||
$class = isset($this->declaringClasses[$column])
|
||||
? $this->declaringClasses[$column]
|
||||
: $this->class;
|
||||
|
||||
// If class is not part of the inheritance, ignore
|
||||
if ( ! ($class->name === $entityName || is_subclass_of($entityName, $class->name))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return array(
|
||||
'class' => $class,
|
||||
'name' => $this->_rsm->fieldMappings[$column],
|
||||
'field' => true,
|
||||
);
|
||||
|
||||
case (isset($this->_rsm->relationMap[$column])):
|
||||
$class = isset($this->_rsm->relationMap[$column])
|
||||
? $this->_rsm->relationMap[$column]
|
||||
: $this->class;
|
||||
|
||||
// If class is not self referencing, ignore
|
||||
if ( ! ($class === $entityName || is_subclass_of($entityName, $class))) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// TODO: Decide what to do with associations. It seems original code is incomplete.
|
||||
// One solution is to load the association, but it might require extra efforts.
|
||||
return array('name' => $column);
|
||||
|
||||
default:
|
||||
return array(
|
||||
'name' => $this->_rsm->metaMappings[$column]
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,37 +13,44 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Internal\Hydration;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Connection,
|
||||
Doctrine\ORM\NoResultException,
|
||||
Doctrine\ORM\NonUniqueResultException;
|
||||
|
||||
/**
|
||||
* Hydrator that hydrates a single scalar value from the result set.
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @since 2.0
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
*/
|
||||
class SingleScalarHydrator extends AbstractHydrator
|
||||
{
|
||||
/** @override */
|
||||
protected function _hydrateAll()
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function hydrateAllData()
|
||||
{
|
||||
$cache = array();
|
||||
$result = $this->_stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
$num = count($result);
|
||||
$data = $this->_stmt->fetchAll(\PDO::FETCH_ASSOC);
|
||||
$numRows = count($data);
|
||||
|
||||
if ($num == 0) {
|
||||
throw new \Doctrine\ORM\NoResultException;
|
||||
} else if ($num > 1 || count($result[key($result)]) > 1) {
|
||||
throw new \Doctrine\ORM\NonUniqueResultException;
|
||||
if ($numRows === 0) {
|
||||
throw new NoResultException();
|
||||
}
|
||||
|
||||
$result = $this->_gatherScalarRowData($result[key($result)], $cache);
|
||||
|
||||
|
||||
if ($numRows > 1 || count($data[key($data)]) > 1) {
|
||||
throw new NonUniqueResultException();
|
||||
}
|
||||
|
||||
$cache = array();
|
||||
$result = $this->gatherScalarRowData($data[key($data)], $cache);
|
||||
|
||||
return array_shift($result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
24
lib/Doctrine/ORM/Mapping/Annotation.php
Normal file
24
lib/Doctrine/ORM/Mapping/Annotation.php
Normal file
@@ -0,0 +1,24 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
interface Annotation
|
||||
{
|
||||
}
|
||||
56
lib/Doctrine/ORM/Mapping/AssociationOverride.php
Normal file
56
lib/Doctrine/ORM/Mapping/AssociationOverride.php
Normal file
@@ -0,0 +1,56 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* This annotation is used to override association mapping of property for an entity relationship.
|
||||
*
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
* @since 2.3
|
||||
*
|
||||
* @Annotation
|
||||
* @Target("ANNOTATION")
|
||||
*/
|
||||
final class AssociationOverride implements Annotation
|
||||
{
|
||||
|
||||
/**
|
||||
* The name of the relationship property whose mapping is being overridden
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* The join column that is being mapped to the persistent attribute.
|
||||
*
|
||||
* @var array<\Doctrine\ORM\Mapping\JoinColumn>
|
||||
*/
|
||||
public $joinColumns;
|
||||
|
||||
|
||||
/**
|
||||
* The join table that maps the relationship.
|
||||
*
|
||||
* @var \Doctrine\ORM\Mapping\JoinTable
|
||||
*/
|
||||
public $joinTable;
|
||||
|
||||
}
|
||||
41
lib/Doctrine/ORM/Mapping/AssociationOverrides.php
Normal file
41
lib/Doctrine/ORM/Mapping/AssociationOverrides.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* This annotation is used to override association mappings of relationship properties.
|
||||
*
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
* @since 2.3
|
||||
*
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
final class AssociationOverrides implements Annotation
|
||||
{
|
||||
|
||||
/**
|
||||
* Mapping overrides of relationship properties
|
||||
*
|
||||
* @var array<\Doctrine\ORM\Mapping\AssociationOverride>
|
||||
*/
|
||||
public $value;
|
||||
|
||||
}
|
||||
47
lib/Doctrine/ORM/Mapping/AttributeOverride.php
Normal file
47
lib/Doctrine/ORM/Mapping/AttributeOverride.php
Normal file
@@ -0,0 +1,47 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* This annotation is used to override the mapping of a entity property.
|
||||
*
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
* @since 2.3
|
||||
*
|
||||
* @Annotation
|
||||
* @Target("ANNOTATION")
|
||||
*/
|
||||
final class AttributeOverride implements Annotation
|
||||
{
|
||||
|
||||
/**
|
||||
* The name of the property whose mapping is being overridden.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* The column definition.
|
||||
*
|
||||
* @var \Doctrine\ORM\Mapping\Column
|
||||
*/
|
||||
public $column;
|
||||
}
|
||||
41
lib/Doctrine/ORM/Mapping/AttributeOverrides.php
Normal file
41
lib/Doctrine/ORM/Mapping/AttributeOverrides.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* This annotation is used to override the mapping of a entity property.
|
||||
*
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
* @since 2.3
|
||||
*
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
final class AttributeOverrides implements Annotation
|
||||
{
|
||||
|
||||
/**
|
||||
* One or more field or property mapping overrides.
|
||||
*
|
||||
* @var array<\Doctrine\ORM\Mapping\AttributeOverride>
|
||||
*/
|
||||
public $value;
|
||||
|
||||
}
|
||||
167
lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php
Normal file
167
lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php
Normal file
@@ -0,0 +1,167 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Builder;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
|
||||
class AssociationBuilder
|
||||
{
|
||||
/**
|
||||
* @var ClassMetadataBuilder
|
||||
*/
|
||||
protected $builder;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $mapping;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
protected $joinColumns;
|
||||
|
||||
/**
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $type;
|
||||
|
||||
/**
|
||||
* @param ClassMetadataBuilder $builder
|
||||
* @param array $mapping
|
||||
*/
|
||||
public function __construct(ClassMetadataBuilder $builder, array $mapping, $type)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$this->mapping = $mapping;
|
||||
$this->type = $type;
|
||||
}
|
||||
|
||||
public function mappedBy($fieldName)
|
||||
{
|
||||
$this->mapping['mappedBy'] = $fieldName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function inversedBy($fieldName)
|
||||
{
|
||||
$this->mapping['inversedBy'] = $fieldName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function cascadeAll()
|
||||
{
|
||||
$this->mapping['cascade'] = array("ALL");
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function cascadePersist()
|
||||
{
|
||||
$this->mapping['cascade'][] = "persist";
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function cascadeRemove()
|
||||
{
|
||||
$this->mapping['cascade'][] = "remove";
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function cascadeMerge()
|
||||
{
|
||||
$this->mapping['cascade'][] = "merge";
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function cascadeDetach()
|
||||
{
|
||||
$this->mapping['cascade'][] = "detach";
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function cascadeRefresh()
|
||||
{
|
||||
$this->mapping['cascade'][] = "refresh";
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function fetchExtraLazy()
|
||||
{
|
||||
$this->mapping['fetch'] = ClassMetadata::FETCH_EXTRA_LAZY;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function fetchEager()
|
||||
{
|
||||
$this->mapping['fetch'] = ClassMetadata::FETCH_EAGER;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function fetchLazy()
|
||||
{
|
||||
$this->mapping['fetch'] = ClassMetadata::FETCH_LAZY;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Join Columns
|
||||
*
|
||||
* @param string $columnName
|
||||
* @param string $referencedColumnName
|
||||
* @param bool $nullable
|
||||
* @param bool $unique
|
||||
* @param string $onDelete
|
||||
* @param string $columnDef
|
||||
*/
|
||||
public function addJoinColumn($columnName, $referencedColumnName, $nullable = true, $unique = false, $onDelete = null, $columnDef = null)
|
||||
{
|
||||
$this->joinColumns[] = array(
|
||||
'name' => $columnName,
|
||||
'referencedColumnName' => $referencedColumnName,
|
||||
'nullable' => $nullable,
|
||||
'unique' => $unique,
|
||||
'onDelete' => $onDelete,
|
||||
'columnDefinition' => $columnDef,
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
$mapping = $this->mapping;
|
||||
if ($this->joinColumns) {
|
||||
$mapping['joinColumns'] = $this->joinColumns;
|
||||
}
|
||||
$cm = $this->builder->getClassMetadata();
|
||||
if ($this->type == ClassMetadata::MANY_TO_ONE) {
|
||||
$cm->mapManyToOne($mapping);
|
||||
} else if ($this->type == ClassMetadata::ONE_TO_ONE) {
|
||||
$cm->mapOneToOne($mapping);
|
||||
} else {
|
||||
throw new \InvalidArgumentException("Type should be a ToOne Assocation here");
|
||||
}
|
||||
return $this->builder;
|
||||
}
|
||||
}
|
||||
470
lib/Doctrine/ORM/Mapping/Builder/ClassMetadataBuilder.php
Normal file
470
lib/Doctrine/ORM/Mapping/Builder/ClassMetadataBuilder.php
Normal file
@@ -0,0 +1,470 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Builder;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadata,
|
||||
Doctrine\ORM\Mapping\ClassMetadataInfo;
|
||||
|
||||
/**
|
||||
* Builder Object for ClassMetadata
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.com
|
||||
* @since 2.2
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
*/
|
||||
class ClassMetadataBuilder
|
||||
{
|
||||
/**
|
||||
* @var \Doctrine\ORM\Mapping\ClassMetadataInfo
|
||||
*/
|
||||
private $cm;
|
||||
|
||||
/**
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadataInfo $cm
|
||||
*/
|
||||
public function __construct(ClassMetadataInfo $cm)
|
||||
{
|
||||
$this->cm = $cm;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClassMetadata
|
||||
*/
|
||||
public function getClassMetadata()
|
||||
{
|
||||
return $this->cm;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark the class as mapped superclass.
|
||||
*
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function setMappedSuperClass()
|
||||
{
|
||||
$this->cm->isMappedSuperclass = true;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set custom Repository class name
|
||||
*
|
||||
* @param string $repositoryClassName
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function setCustomRepositoryClass($repositoryClassName)
|
||||
{
|
||||
$this->cm->setCustomRepositoryClass($repositoryClassName);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark class read only
|
||||
*
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function setReadOnly()
|
||||
{
|
||||
$this->cm->markReadOnly();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the table name
|
||||
*
|
||||
* @param string $name
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function setTable($name)
|
||||
{
|
||||
$this->cm->setPrimaryTable(array('name' => $name));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Index
|
||||
*
|
||||
* @param array $columns
|
||||
* @param string $name
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function addIndex(array $columns, $name)
|
||||
{
|
||||
if (!isset($this->cm->table['indexes'])) {
|
||||
$this->cm->table['indexes'] = array();
|
||||
}
|
||||
|
||||
$this->cm->table['indexes'][$name] = array('columns' => $columns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Unique Constraint
|
||||
*
|
||||
* @param array $columns
|
||||
* @param string $name
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function addUniqueConstraint(array $columns, $name)
|
||||
{
|
||||
if ( ! isset($this->cm->table['uniqueConstraints'])) {
|
||||
$this->cm->table['uniqueConstraints'] = array();
|
||||
}
|
||||
|
||||
$this->cm->table['uniqueConstraints'][$name] = array('columns' => $columns);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add named query
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $dqlQuery
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function addNamedQuery($name, $dqlQuery)
|
||||
{
|
||||
$this->cm->addNamedQuery(array(
|
||||
'name' => $name,
|
||||
'query' => $dqlQuery,
|
||||
));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set class as root of a joined table inheritance hierachy.
|
||||
*
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function setJoinedTableInheritance()
|
||||
{
|
||||
$this->cm->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_JOINED);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set class as root of a single table inheritance hierachy.
|
||||
*
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function setSingleTableInheritance()
|
||||
{
|
||||
$this->cm->setInheritanceType(ClassMetadata::INHERITANCE_TYPE_SINGLE_TABLE);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the discriminator column details.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
*/
|
||||
public function setDiscriminatorColumn($name, $type = 'string', $length = 255)
|
||||
{
|
||||
$this->cm->setDiscriminatorColumn(array(
|
||||
'name' => $name,
|
||||
'type' => $type,
|
||||
'length' => $length,
|
||||
));
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a subclass to this inheritance hierachy.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $class
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function addDiscriminatorMapClass($name, $class)
|
||||
{
|
||||
$this->cm->addDiscriminatorMapClass($name, $class);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set deferred explicit change tracking policy.
|
||||
*
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function setChangeTrackingPolicyDeferredExplicit()
|
||||
{
|
||||
$this->cm->setChangeTrackingPolicy(ClassMetadata::CHANGETRACKING_DEFERRED_EXPLICIT);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set notify change tracking policy.
|
||||
*
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function setChangeTrackingPolicyNotify()
|
||||
{
|
||||
$this->cm->setChangeTrackingPolicy(ClassMetadata::CHANGETRACKING_NOTIFY);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add lifecycle event
|
||||
*
|
||||
* @param string $methodName
|
||||
* @param string $event
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function addLifecycleEvent($methodName, $event)
|
||||
{
|
||||
$this->cm->addLifecycleCallback($methodName, $event);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Field
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @param array $mapping
|
||||
*/
|
||||
public function addField($name, $type, array $mapping = array())
|
||||
{
|
||||
$mapping['fieldName'] = $name;
|
||||
$mapping['type'] = $type;
|
||||
|
||||
$this->cm->mapField($mapping);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a field builder.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $type
|
||||
* @return FieldBuilder
|
||||
*/
|
||||
public function createField($name, $type)
|
||||
{
|
||||
return new FieldBuilder(
|
||||
$this,
|
||||
array(
|
||||
'fieldName' => $name,
|
||||
'type' => $type
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a simple many to one association, optionally with the inversed by field.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $targetEntity
|
||||
* @param string|null $inversedBy
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function addManyToOne($name, $targetEntity, $inversedBy = null)
|
||||
{
|
||||
$builder = $this->createManyToOne($name, $targetEntity);
|
||||
|
||||
if ($inversedBy) {
|
||||
$builder->inversedBy($inversedBy);
|
||||
}
|
||||
|
||||
return $builder->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a ManyToOne Assocation Builder.
|
||||
*
|
||||
* Note: This method does not add the association, you have to call build() on the AssociationBuilder.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $targetEntity
|
||||
* @return AssociationBuilder
|
||||
*/
|
||||
public function createManyToOne($name, $targetEntity)
|
||||
{
|
||||
return new AssociationBuilder(
|
||||
$this,
|
||||
array(
|
||||
'fieldName' => $name,
|
||||
'targetEntity' => $targetEntity
|
||||
),
|
||||
ClassMetadata::MANY_TO_ONE
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create OneToOne Assocation Builder
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $targetEntity
|
||||
* @return AssociationBuilder
|
||||
*/
|
||||
public function createOneToOne($name, $targetEntity)
|
||||
{
|
||||
return new AssociationBuilder(
|
||||
$this,
|
||||
array(
|
||||
'fieldName' => $name,
|
||||
'targetEntity' => $targetEntity
|
||||
),
|
||||
ClassMetadata::ONE_TO_ONE
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add simple inverse one-to-one assocation.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $targetEntity
|
||||
* @param string $mappedBy
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function addInverseOneToOne($name, $targetEntity, $mappedBy)
|
||||
{
|
||||
$builder = $this->createOneToOne($name, $targetEntity);
|
||||
$builder->mappedBy($mappedBy);
|
||||
|
||||
return $builder->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add simple owning one-to-one assocation.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $targetEntity
|
||||
* @param string $inversedBy
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function addOwningOneToOne($name, $targetEntity, $inversedBy = null)
|
||||
{
|
||||
$builder = $this->createOneToOne($name, $targetEntity);
|
||||
|
||||
if ($inversedBy) {
|
||||
$builder->inversedBy($inversedBy);
|
||||
}
|
||||
|
||||
return $builder->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create ManyToMany Assocation Builder
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $targetEntity
|
||||
* @return ManyToManyAssociationBuilder
|
||||
*/
|
||||
public function createManyToMany($name, $targetEntity)
|
||||
{
|
||||
return new ManyToManyAssociationBuilder(
|
||||
$this,
|
||||
array(
|
||||
'fieldName' => $name,
|
||||
'targetEntity' => $targetEntity
|
||||
),
|
||||
ClassMetadata::MANY_TO_MANY
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a simple owning many to many assocation.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $targetEntity
|
||||
* @param string|null $inversedBy
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function addOwningManyToMany($name, $targetEntity, $inversedBy = null)
|
||||
{
|
||||
$builder = $this->createManyToMany($name, $targetEntity);
|
||||
|
||||
if ($inversedBy) {
|
||||
$builder->inversedBy($inversedBy);
|
||||
}
|
||||
|
||||
return $builder->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a simple inverse many to many assocation.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $targetEntity
|
||||
* @param string $mappedBy
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function addInverseManyToMany($name, $targetEntity, $mappedBy)
|
||||
{
|
||||
$builder = $this->createManyToMany($name, $targetEntity);
|
||||
$builder->mappedBy($mappedBy);
|
||||
|
||||
return $builder->build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a one to many assocation builder
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $targetEntity
|
||||
* @return OneToManyAssociationBuilder
|
||||
*/
|
||||
public function createOneToMany($name, $targetEntity)
|
||||
{
|
||||
return new OneToManyAssociationBuilder(
|
||||
$this,
|
||||
array(
|
||||
'fieldName' => $name,
|
||||
'targetEntity' => $targetEntity
|
||||
),
|
||||
ClassMetadata::ONE_TO_MANY
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add simple OneToMany assocation.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $targetEntity
|
||||
* @param string $mappedBy
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function addOneToMany($name, $targetEntity, $mappedBy)
|
||||
{
|
||||
$builder = $this->createOneToMany($name, $targetEntity);
|
||||
$builder->mappedBy($mappedBy);
|
||||
|
||||
return $builder->build();
|
||||
}
|
||||
}
|
||||
223
lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php
Normal file
223
lib/Doctrine/ORM/Mapping/Builder/FieldBuilder.php
Normal file
@@ -0,0 +1,223 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Builder;
|
||||
|
||||
/**
|
||||
* Field Builder
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.com
|
||||
* @since 2.2
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class FieldBuilder
|
||||
{
|
||||
/**
|
||||
* @var ClassMetadataBuilder
|
||||
*/
|
||||
private $builder;
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $mapping;
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $version;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $generatedValue;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $sequenceDef;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param ClassMetadataBuilder $builder
|
||||
* @param array $mapping
|
||||
*/
|
||||
public function __construct(ClassMetadataBuilder $builder, array $mapping)
|
||||
{
|
||||
$this->builder = $builder;
|
||||
$this->mapping = $mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set length.
|
||||
*
|
||||
* @param int $length
|
||||
* @return FieldBuilder
|
||||
*/
|
||||
public function length($length)
|
||||
{
|
||||
$this->mapping['length'] = $length;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set nullable
|
||||
*
|
||||
* @param bool
|
||||
* @return FieldBuilder
|
||||
*/
|
||||
public function nullable($flag = true)
|
||||
{
|
||||
$this->mapping['nullable'] = (bool)$flag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Unique
|
||||
*
|
||||
* @param bool
|
||||
* @return FieldBuilder
|
||||
*/
|
||||
public function unique($flag = true)
|
||||
{
|
||||
$this->mapping['unique'] = (bool)$flag;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set column name
|
||||
*
|
||||
* @param string $name
|
||||
* @return FieldBuilder
|
||||
*/
|
||||
public function columnName($name)
|
||||
{
|
||||
$this->mapping['columnName'] = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Precision
|
||||
*
|
||||
* @param int $p
|
||||
* @return FieldBuilder
|
||||
*/
|
||||
public function precision($p)
|
||||
{
|
||||
$this->mapping['precision'] = $p;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set scale.
|
||||
*
|
||||
* @param int $s
|
||||
* @return FieldBuilder
|
||||
*/
|
||||
public function scale($s)
|
||||
{
|
||||
$this->mapping['scale'] = $s;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set field as primary key.
|
||||
*
|
||||
* @return FieldBuilder
|
||||
*/
|
||||
public function isPrimaryKey()
|
||||
{
|
||||
$this->mapping['id'] = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $strategy
|
||||
* @return FieldBuilder
|
||||
*/
|
||||
public function generatedValue($strategy = 'AUTO')
|
||||
{
|
||||
$this->generatedValue = $strategy;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set field versioned
|
||||
*
|
||||
* @return FieldBuilder
|
||||
*/
|
||||
public function isVersionField()
|
||||
{
|
||||
$this->version = true;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Sequence Generator
|
||||
*
|
||||
* @param string $sequenceName
|
||||
* @param int $allocationSize
|
||||
* @param int $initialValue
|
||||
* @return FieldBuilder
|
||||
*/
|
||||
public function setSequenceGenerator($sequenceName, $allocationSize = 1, $initialValue = 1)
|
||||
{
|
||||
$this->sequenceDef = array(
|
||||
'sequenceName' => $sequenceName,
|
||||
'allocationSize' => $allocationSize,
|
||||
'initialValue' => $initialValue,
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set column definition.
|
||||
*
|
||||
* @param string $def
|
||||
* @return FieldBuilder
|
||||
*/
|
||||
public function columnDefinition($def)
|
||||
{
|
||||
$this->mapping['columnDefinition'] = $def;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finalize this field and attach it to the ClassMetadata.
|
||||
*
|
||||
* Without this call a FieldBuilder has no effect on the ClassMetadata.
|
||||
*
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
$cm = $this->builder->getClassMetadata();
|
||||
if ($this->generatedValue) {
|
||||
$cm->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $this->generatedValue));
|
||||
}
|
||||
if ($this->version) {
|
||||
$cm->setVersionMapping($this->mapping);
|
||||
}
|
||||
$cm->mapField($this->mapping);
|
||||
if ($this->sequenceDef) {
|
||||
$cm->setSequenceGeneratorDefinition($this->sequenceDef);
|
||||
}
|
||||
return $this->builder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Builder;
|
||||
|
||||
/**
|
||||
* ManyToMany Association Builder
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.com
|
||||
* @since 2.0
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class ManyToManyAssociationBuilder extends OneToManyAssociationBuilder
|
||||
{
|
||||
private $joinTableName;
|
||||
|
||||
private $inverseJoinColumns = array();
|
||||
|
||||
public function setJoinTable($name)
|
||||
{
|
||||
$this->joinTableName = $name;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add Inverse Join Columns
|
||||
*
|
||||
* @param string $columnName
|
||||
* @param string $referencedColumnName
|
||||
* @param bool $nullable
|
||||
* @param bool $unique
|
||||
* @param string $onDelete
|
||||
* @param string $columnDef
|
||||
*/
|
||||
public function addInverseJoinColumn($columnName, $referencedColumnName, $nullable = true, $unique = false, $onDelete = null, $columnDef = null)
|
||||
{
|
||||
$this->inverseJoinColumns[] = array(
|
||||
'name' => $columnName,
|
||||
'referencedColumnName' => $referencedColumnName,
|
||||
'nullable' => $nullable,
|
||||
'unique' => $unique,
|
||||
'onDelete' => $onDelete,
|
||||
'columnDefinition' => $columnDef,
|
||||
);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
$mapping = $this->mapping;
|
||||
$mapping['joinTable'] = array();
|
||||
if ($this->joinColumns) {
|
||||
$mapping['joinTable']['joinColumns'] = $this->joinColumns;
|
||||
}
|
||||
if ($this->inverseJoinColumns) {
|
||||
$mapping['joinTable']['inverseJoinColumns'] = $this->inverseJoinColumns;
|
||||
}
|
||||
if ($this->joinTableName) {
|
||||
$mapping['joinTable']['name'] = $this->joinTableName;
|
||||
}
|
||||
$cm = $this->builder->getClassMetadata();
|
||||
$cm->mapManyToMany($mapping);
|
||||
return $this->builder;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Builder;
|
||||
|
||||
/**
|
||||
* OneToMany Association Builder
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.com
|
||||
* @since 2.0
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class OneToManyAssociationBuilder extends AssociationBuilder
|
||||
{
|
||||
/**
|
||||
* @param array $fieldNames
|
||||
* @return OneToManyAssociationBuilder
|
||||
*/
|
||||
public function setOrderBy(array $fieldNames)
|
||||
{
|
||||
$this->mapping['orderBy'] = $fieldNames;
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setIndexBy($fieldName)
|
||||
{
|
||||
$this->mapping['indexBy'] = $fieldName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ClassMetadataBuilder
|
||||
*/
|
||||
public function build()
|
||||
{
|
||||
$mapping = $this->mapping;
|
||||
if ($this->joinColumns) {
|
||||
$mapping['joinColumns'] = $this->joinColumns;
|
||||
}
|
||||
$cm = $this->builder->getClassMetadata();
|
||||
$cm->mapOneToMany($mapping);
|
||||
return $this->builder;
|
||||
}
|
||||
}
|
||||
30
lib/Doctrine/ORM/Mapping/ChangeTrackingPolicy.php
Normal file
30
lib/Doctrine/ORM/Mapping/ChangeTrackingPolicy.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
final class ChangeTrackingPolicy implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $value;
|
||||
}
|
||||
@@ -13,364 +13,17 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use ReflectionClass, ReflectionProperty;
|
||||
|
||||
/**
|
||||
* A <tt>ClassMetadata</tt> instance holds all the object-relational mapping metadata
|
||||
* of an entity and it's associations.
|
||||
*
|
||||
* Once populated, ClassMetadata instances are usually cached in a serialized form.
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* <b>IMPORTANT NOTE:</b>
|
||||
*
|
||||
* The fields of this class are only public for 2 reasons:
|
||||
* 1) To allow fast READ access.
|
||||
* 2) To drastically reduce the size of a serialized instance (private/protected members
|
||||
* get the whole class name, namespace inclusive, prepended to every property in
|
||||
* the serialized representation).
|
||||
*
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @author Jonathan H. Wage <jonwage@gmail.com>
|
||||
* @since 2.0
|
||||
* @todo remove or rename ClassMetadataInfo to ClassMetadata
|
||||
*/
|
||||
class ClassMetadata extends ClassMetadataInfo
|
||||
{
|
||||
/**
|
||||
* The ReflectionProperty instances of the mapped class.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
public $reflFields = array();
|
||||
|
||||
/**
|
||||
* The prototype from which new instances of the mapped class are created.
|
||||
*
|
||||
* @var object
|
||||
*/
|
||||
private $_prototype;
|
||||
|
||||
/**
|
||||
* Initializes a new ClassMetadata instance that will hold the object-relational mapping
|
||||
* metadata of the class with the given name.
|
||||
*
|
||||
* @param string $entityName The name of the entity class the new instance is used for.
|
||||
*/
|
||||
public function __construct($entityName)
|
||||
{
|
||||
parent::__construct($entityName);
|
||||
$this->reflClass = new ReflectionClass($entityName);
|
||||
$this->namespace = $this->reflClass->getNamespaceName();
|
||||
$this->table['name'] = $this->reflClass->getShortName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ReflectionPropertys of the mapped class.
|
||||
*
|
||||
* @return array An array of ReflectionProperty instances.
|
||||
*/
|
||||
public function getReflectionProperties()
|
||||
{
|
||||
return $this->reflFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a ReflectionProperty for a specific field of the mapped class.
|
||||
*
|
||||
* @param string $name
|
||||
* @return ReflectionProperty
|
||||
*/
|
||||
public function getReflectionProperty($name)
|
||||
{
|
||||
return $this->reflFields[$name];
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ReflectionProperty for the single identifier field.
|
||||
*
|
||||
* @return ReflectionProperty
|
||||
* @throws BadMethodCallException If the class has a composite identifier.
|
||||
*/
|
||||
public function getSingleIdReflectionProperty()
|
||||
{
|
||||
if ($this->isIdentifierComposite) {
|
||||
throw new \BadMethodCallException("Class " . $this->name . " has a composite identifier.");
|
||||
}
|
||||
return $this->reflFields[$this->identifier[0]];
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates & completes the given field mapping.
|
||||
*
|
||||
* @param array $mapping The field mapping to validated & complete.
|
||||
* @return array The validated and completed field mapping.
|
||||
*
|
||||
* @throws MappingException
|
||||
*/
|
||||
protected function _validateAndCompleteFieldMapping(array &$mapping)
|
||||
{
|
||||
parent::_validateAndCompleteFieldMapping($mapping);
|
||||
|
||||
// Store ReflectionProperty of mapped field
|
||||
$refProp = $this->reflClass->getProperty($mapping['fieldName']);
|
||||
$refProp->setAccessible(true);
|
||||
$this->reflFields[$mapping['fieldName']] = $refProp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the identifier values of an entity of this class.
|
||||
*
|
||||
* For composite identifiers, the identifier values are returned as an array
|
||||
* with the same order as the field order in {@link identifier}.
|
||||
*
|
||||
* @param object $entity
|
||||
* @return array
|
||||
*/
|
||||
public function getIdentifierValues($entity)
|
||||
{
|
||||
if ($this->isIdentifierComposite) {
|
||||
$id = array();
|
||||
foreach ($this->identifier as $idField) {
|
||||
$value = $this->reflFields[$idField]->getValue($entity);
|
||||
if ($value !== null) {
|
||||
$id[$idField] = $value;
|
||||
}
|
||||
}
|
||||
return $id;
|
||||
} else {
|
||||
$value = $this->reflFields[$this->identifier[0]]->getValue($entity);
|
||||
if ($value !== null) {
|
||||
return array($this->identifier[0] => $value);
|
||||
}
|
||||
return array();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates the entity identifier of an entity.
|
||||
*
|
||||
* @param object $entity
|
||||
* @param mixed $id
|
||||
* @todo Rename to assignIdentifier()
|
||||
*/
|
||||
public function setIdentifierValues($entity, array $id)
|
||||
{
|
||||
foreach ($id as $idField => $idValue) {
|
||||
$this->reflFields[$idField]->setValue($entity, $idValue);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the specified field to the specified value on the given entity.
|
||||
*
|
||||
* @param object $entity
|
||||
* @param string $field
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function setFieldValue($entity, $field, $value)
|
||||
{
|
||||
$this->reflFields[$field]->setValue($entity, $value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the specified field's value off the given entity.
|
||||
*
|
||||
* @param object $entity
|
||||
* @param string $field
|
||||
*/
|
||||
public function getFieldValue($entity, $field)
|
||||
{
|
||||
return $this->reflFields[$field]->getValue($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the association mapping.
|
||||
*
|
||||
* @param AssociationMapping $assocMapping
|
||||
*/
|
||||
protected function _storeAssociationMapping(array $assocMapping)
|
||||
{
|
||||
parent::_storeAssociationMapping($assocMapping);
|
||||
|
||||
// Store ReflectionProperty of mapped field
|
||||
$sourceFieldName = $assocMapping['fieldName'];
|
||||
|
||||
$refProp = $this->reflClass->getProperty($sourceFieldName);
|
||||
$refProp->setAccessible(true);
|
||||
$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.
|
||||
*
|
||||
* @return string The string representation of this instance.
|
||||
* @todo Construct meaningful string representation.
|
||||
*/
|
||||
public function __toString()
|
||||
{
|
||||
return __CLASS__ . '@' . spl_object_hash($this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines which fields get serialized.
|
||||
*
|
||||
* It is only serialized what is necessary for best unserialization performance.
|
||||
* That means any metadata properties that are not set or empty or simply have
|
||||
* their default value are NOT serialized.
|
||||
*
|
||||
* Parts that are also NOT serialized because they can not be properly unserialized:
|
||||
* - reflClass (ReflectionClass)
|
||||
* - reflFields (ReflectionProperty array)
|
||||
*
|
||||
* @return array The names of all the fields that should be serialized.
|
||||
*/
|
||||
public function __sleep()
|
||||
{
|
||||
// This metadata is always serialized/cached.
|
||||
$serialized = array(
|
||||
'associationMappings',
|
||||
'columnNames', //TODO: Not really needed. Can use fieldMappings[$fieldName]['columnName']
|
||||
'fieldMappings',
|
||||
'fieldNames',
|
||||
'identifier',
|
||||
'isIdentifierComposite', // TODO: REMOVE
|
||||
'name',
|
||||
'namespace', // TODO: REMOVE
|
||||
'table',
|
||||
'rootEntityName',
|
||||
'idGenerator', //TODO: Does not really need to be serialized. Could be moved to runtime.
|
||||
);
|
||||
|
||||
// The rest of the metadata is only serialized if necessary.
|
||||
if ($this->changeTrackingPolicy != self::CHANGETRACKING_DEFERRED_IMPLICIT) {
|
||||
$serialized[] = 'changeTrackingPolicy';
|
||||
}
|
||||
|
||||
if ($this->customRepositoryClassName) {
|
||||
$serialized[] = 'customRepositoryClassName';
|
||||
}
|
||||
|
||||
if ($this->inheritanceType != self::INHERITANCE_TYPE_NONE) {
|
||||
$serialized[] = 'inheritanceType';
|
||||
$serialized[] = 'discriminatorColumn';
|
||||
$serialized[] = 'discriminatorValue';
|
||||
$serialized[] = 'discriminatorMap';
|
||||
$serialized[] = 'parentClasses';
|
||||
$serialized[] = 'subClasses';
|
||||
}
|
||||
|
||||
if ($this->generatorType != self::GENERATOR_TYPE_NONE) {
|
||||
$serialized[] = 'generatorType';
|
||||
if ($this->generatorType == self::GENERATOR_TYPE_SEQUENCE) {
|
||||
$serialized[] = 'sequenceGeneratorDefinition';
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->isMappedSuperclass) {
|
||||
$serialized[] = 'isMappedSuperclass';
|
||||
}
|
||||
|
||||
if ($this->isVersioned) {
|
||||
$serialized[] = 'isVersioned';
|
||||
$serialized[] = 'versionField';
|
||||
}
|
||||
|
||||
if ($this->lifecycleCallbacks) {
|
||||
$serialized[] = 'lifecycleCallbacks';
|
||||
}
|
||||
|
||||
return $serialized;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores some state that can not be serialized/unserialized.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __wakeup()
|
||||
{
|
||||
// Restore ReflectionClass and properties
|
||||
$this->reflClass = new ReflectionClass($this->name);
|
||||
|
||||
foreach ($this->fieldMappings as $field => $mapping) {
|
||||
if (isset($mapping['declared'])) {
|
||||
$reflField = new ReflectionProperty($mapping['declared'], $field);
|
||||
} else {
|
||||
$reflField = $this->reflClass->getProperty($field);
|
||||
}
|
||||
$reflField->setAccessible(true);
|
||||
$this->reflFields[$field] = $reflField;
|
||||
}
|
||||
|
||||
foreach ($this->associationMappings as $field => $mapping) {
|
||||
if (isset($mapping['declared'])) {
|
||||
$reflField = new ReflectionProperty($mapping['declared'], $field);
|
||||
} else {
|
||||
$reflField = $this->reflClass->getProperty($field);
|
||||
}
|
||||
|
||||
$reflField->setAccessible(true);
|
||||
$this->reflFields[$field] = $reflField;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new instance of the mapped class, without invoking the constructor.
|
||||
*
|
||||
* @return object
|
||||
*/
|
||||
public function newInstance()
|
||||
{
|
||||
if ($this->_prototype === null) {
|
||||
$this->_prototype = unserialize(sprintf('O:%d:"%s":0:{}', strlen($this->name), $this->name));
|
||||
}
|
||||
return clone $this->_prototype;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
@@ -23,11 +23,16 @@ use ReflectionException,
|
||||
Doctrine\ORM\ORMException,
|
||||
Doctrine\ORM\EntityManager,
|
||||
Doctrine\DBAL\Platforms,
|
||||
Doctrine\ORM\Events;
|
||||
Doctrine\ORM\Events,
|
||||
Doctrine\Common\Persistence\Mapping\ReflectionService,
|
||||
Doctrine\Common\Persistence\Mapping\ClassMetadata as ClassMetadataInterface,
|
||||
Doctrine\Common\Persistence\Mapping\AbstractClassMetadataFactory,
|
||||
Doctrine\ORM\Id\IdentityGenerator,
|
||||
Doctrine\ORM\Event\LoadClassMetadataEventArgs;
|
||||
|
||||
/**
|
||||
* The ClassMetadataFactory is used to create ClassMetadata objects that contain all the
|
||||
* metadata mapping informations of a class which describes how a class should be mapped
|
||||
* metadata mapping information of a class which describes how a class should be mapped
|
||||
* to a relational database.
|
||||
*
|
||||
* @since 2.0
|
||||
@@ -36,20 +41,20 @@ use ReflectionException,
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class ClassMetadataFactory
|
||||
class ClassMetadataFactory extends AbstractClassMetadataFactory
|
||||
{
|
||||
/**
|
||||
* @var EntityManager
|
||||
*/
|
||||
private $em;
|
||||
|
||||
|
||||
/**
|
||||
* @var AbstractPlatform
|
||||
* @var \Doctrine\DBAL\Platforms\AbstractPlatform
|
||||
*/
|
||||
private $targetPlatform;
|
||||
|
||||
/**
|
||||
* @var Driver\Driver
|
||||
* @var \Doctrine\Common\Persistence\Mapping\Driver\MappingDriver
|
||||
*/
|
||||
private $driver;
|
||||
|
||||
@@ -59,22 +64,7 @@ class ClassMetadataFactory
|
||||
private $evm;
|
||||
|
||||
/**
|
||||
* @var \Doctrine\Common\Cache\Cache
|
||||
*/
|
||||
private $cacheDriver;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $loadedMetadata = array();
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
*/
|
||||
private $initialized = false;
|
||||
|
||||
/**
|
||||
* @param EntityManager $$em
|
||||
* @param EntityManager $em
|
||||
*/
|
||||
public function setEntityManager(EntityManager $em)
|
||||
{
|
||||
@@ -82,55 +72,9 @@ class ClassMetadataFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache driver used by the factory to cache ClassMetadata instances.
|
||||
*
|
||||
* @param Doctrine\Common\Cache\Cache $cacheDriver
|
||||
* {@inheritDoc}.
|
||||
*/
|
||||
public function setCacheDriver($cacheDriver)
|
||||
{
|
||||
$this->cacheDriver = $cacheDriver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cache driver used by the factory to cache ClassMetadata instances.
|
||||
*
|
||||
* @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()
|
||||
{
|
||||
if ( ! $this->initialized) {
|
||||
$this->initialize();
|
||||
}
|
||||
|
||||
$metadata = array();
|
||||
foreach ($this->driver->getAllClassNames() as $className) {
|
||||
$metadata[] = $this->getMetadataFor($className);
|
||||
}
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Lazy initialization of this stuff, especially the metadata driver,
|
||||
* since these are not needed at all when a metadata cache is active.
|
||||
*/
|
||||
private function initialize()
|
||||
protected function initialize()
|
||||
{
|
||||
$this->driver = $this->em->getConfiguration()->getMetadataDriverImpl();
|
||||
$this->targetPlatform = $this->em->getConnection()->getDatabasePlatform();
|
||||
@@ -139,227 +83,202 @@ class ClassMetadataFactory
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the class metadata descriptor for a class.
|
||||
*
|
||||
* @param string $className The name of the class.
|
||||
* @return Doctrine\ORM\Mapping\ClassMetadata
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getMetadataFor($className)
|
||||
protected function doLoadMetadata($class, $parent, $rootEntityFound, array $nonSuperclassParents)
|
||||
{
|
||||
if ( ! isset($this->loadedMetadata[$className])) {
|
||||
$realClassName = $className;
|
||||
/* @var $class ClassMetadata */
|
||||
/* @var $parent ClassMetadata */
|
||||
if ($parent) {
|
||||
$class->setInheritanceType($parent->inheritanceType);
|
||||
$class->setDiscriminatorColumn($parent->discriminatorColumn);
|
||||
$class->setIdGeneratorType($parent->generatorType);
|
||||
$this->addInheritedFields($class, $parent);
|
||||
$this->addInheritedRelations($class, $parent);
|
||||
$class->setIdentifier($parent->identifier);
|
||||
$class->setVersioned($parent->isVersioned);
|
||||
$class->setVersionField($parent->versionField);
|
||||
$class->setDiscriminatorMap($parent->discriminatorMap);
|
||||
$class->setLifecycleCallbacks($parent->lifecycleCallbacks);
|
||||
$class->setChangeTrackingPolicy($parent->changeTrackingPolicy);
|
||||
|
||||
// Check for namespace alias
|
||||
if (strpos($className, ':') !== false) {
|
||||
list($namespaceAlias, $simpleClassName) = explode(':', $className);
|
||||
$realClassName = $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName;
|
||||
|
||||
if (isset($this->loadedMetadata[$realClassName])) {
|
||||
// We do not have the alias name in the map, include it
|
||||
$this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName];
|
||||
|
||||
return $this->loadedMetadata[$realClassName];
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->cacheDriver) {
|
||||
if (($cached = $this->cacheDriver->fetch("$realClassName\$CLASSMETADATA")) !== false) {
|
||||
$this->loadedMetadata[$realClassName] = $cached;
|
||||
} else {
|
||||
foreach ($this->loadMetadata($realClassName) as $loadedClassName) {
|
||||
$this->cacheDriver->save(
|
||||
"$loadedClassName\$CLASSMETADATA", $this->loadedMetadata[$loadedClassName], null
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$this->loadMetadata($realClassName);
|
||||
}
|
||||
|
||||
if ($className != $realClassName) {
|
||||
// We do not have the alias name in the map, include it
|
||||
$this->loadedMetadata[$className] = $this->loadedMetadata[$realClassName];
|
||||
if ($parent->isMappedSuperclass) {
|
||||
$class->setCustomRepositoryClass($parent->customRepositoryClassName);
|
||||
}
|
||||
}
|
||||
|
||||
return $this->loadedMetadata[$className];
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
public function hasMetadataFor($className)
|
||||
{
|
||||
return isset($this->loadedMetadata[$className]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the metadata descriptor for a specific class.
|
||||
*
|
||||
* NOTE: This is only useful in very special cases, like when generating proxy classes.
|
||||
*
|
||||
* @param string $className
|
||||
* @param ClassMetadata $class
|
||||
*/
|
||||
public function setMetadataFor($className, $class)
|
||||
{
|
||||
$this->loadedMetadata[$className] = $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get array of parent classes for the given entity class
|
||||
*
|
||||
* @param string $name
|
||||
* @return array $parentClasses
|
||||
*/
|
||||
protected function getParentClasses($name)
|
||||
{
|
||||
// Collect parent classes, ignoring transient (not-mapped) classes.
|
||||
$parentClasses = array();
|
||||
foreach (array_reverse(class_parents($name)) as $parentClass) {
|
||||
if ( ! $this->driver->isTransient($parentClass)) {
|
||||
$parentClasses[] = $parentClass;
|
||||
}
|
||||
}
|
||||
return $parentClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the metadata of the class in question and all it's ancestors whose metadata
|
||||
* is still not loaded.
|
||||
*
|
||||
* @param string $name The name of the class for which the metadata should get loaded.
|
||||
* @param array $tables The metadata collection to which the loaded metadata is added.
|
||||
*/
|
||||
protected function loadMetadata($name)
|
||||
{
|
||||
if ( ! $this->initialized) {
|
||||
$this->initialize();
|
||||
// Invoke driver
|
||||
try {
|
||||
$this->driver->loadMetadataForClass($class->getName(), $class);
|
||||
} catch (ReflectionException $e) {
|
||||
throw MappingException::reflectionFailure($class->getName(), $e);
|
||||
}
|
||||
|
||||
$loaded = array();
|
||||
|
||||
$parentClasses = $this->getParentClasses($name);
|
||||
$parentClasses[] = $name;
|
||||
|
||||
// Move down the hierarchy of parent classes, starting from the topmost class
|
||||
$parent = null;
|
||||
$visited = array();
|
||||
foreach ($parentClasses as $className) {
|
||||
if (isset($this->loadedMetadata[$className])) {
|
||||
$parent = $this->loadedMetadata[$className];
|
||||
if ( ! $parent->isMappedSuperclass) {
|
||||
array_unshift($visited, $className);
|
||||
}
|
||||
continue;
|
||||
// If this class has a parent the id generator strategy is inherited.
|
||||
// However this is only true if the hierarchy of parents contains the root entity,
|
||||
// if it consists of mapped superclasses these don't necessarily include the id field.
|
||||
if ($parent && $rootEntityFound) {
|
||||
if ($parent->isIdGeneratorSequence()) {
|
||||
$class->setSequenceGeneratorDefinition($parent->sequenceGeneratorDefinition);
|
||||
} else if ($parent->isIdGeneratorTable()) {
|
||||
$class->tableGeneratorDefinition = $parent->tableGeneratorDefinition;
|
||||
}
|
||||
|
||||
$class = $this->newClassMetadataInstance($className);
|
||||
|
||||
if ($parent) {
|
||||
if (!$parent->isMappedSuperclass) {
|
||||
$class->setInheritanceType($parent->inheritanceType);
|
||||
$class->setDiscriminatorColumn($parent->discriminatorColumn);
|
||||
}
|
||||
if ($parent->generatorType) {
|
||||
$class->setIdGeneratorType($parent->generatorType);
|
||||
$this->addInheritedFields($class, $parent);
|
||||
$this->addInheritedRelations($class, $parent);
|
||||
$class->setIdentifier($parent->identifier);
|
||||
$class->setVersioned($parent->isVersioned);
|
||||
$class->setVersionField($parent->versionField);
|
||||
if (!$parent->isMappedSuperclass) {
|
||||
$class->setDiscriminatorMap($parent->discriminatorMap);
|
||||
}
|
||||
$class->setLifecycleCallbacks($parent->lifecycleCallbacks);
|
||||
$class->setChangeTrackingPolicy($parent->changeTrackingPolicy);
|
||||
}
|
||||
|
||||
// Invoke driver
|
||||
try {
|
||||
$this->driver->loadMetadataForClass($className, $class);
|
||||
} catch (ReflectionException $e) {
|
||||
throw MappingException::reflectionFailure($className, $e);
|
||||
if ($parent->idGenerator) {
|
||||
$class->setIdGenerator($parent->idGenerator);
|
||||
}
|
||||
} else {
|
||||
$this->completeIdGeneratorMapping($class);
|
||||
}
|
||||
|
||||
if ($parent && ! $parent->isMappedSuperclass) {
|
||||
if ($parent->isIdGeneratorSequence()) {
|
||||
$class->setSequenceGeneratorDefinition($parent->sequenceGeneratorDefinition);
|
||||
} else if ($parent->isIdGeneratorTable()) {
|
||||
$class->getTableGeneratorDefinition($parent->tableGeneratorDefinition);
|
||||
}
|
||||
if ($parent->generatorType) {
|
||||
$class->setIdGeneratorType($parent->generatorType);
|
||||
}
|
||||
if ($parent->idGenerator) {
|
||||
$class->setIdGenerator($parent->idGenerator);
|
||||
}
|
||||
} else {
|
||||
$this->completeIdGeneratorMapping($class);
|
||||
}
|
||||
if ($parent && $parent->isInheritanceTypeSingleTable()) {
|
||||
$class->setPrimaryTable($parent->table);
|
||||
}
|
||||
|
||||
if ($parent && $parent->isInheritanceTypeSingleTable()) {
|
||||
$class->setPrimaryTable($parent->table);
|
||||
}
|
||||
if ($parent && $parent->containsForeignIdentifier) {
|
||||
$class->containsForeignIdentifier = true;
|
||||
}
|
||||
|
||||
$class->setParentClasses($visited);
|
||||
if ($parent && !empty($parent->namedQueries)) {
|
||||
$this->addInheritedNamedQueries($class, $parent);
|
||||
}
|
||||
|
||||
if ($this->evm->hasListeners(Events::loadClassMetadata)) {
|
||||
$eventArgs = new \Doctrine\ORM\Event\LoadClassMetadataEventArgs($class, $this->em);
|
||||
$this->evm->dispatchEvent(Events::loadClassMetadata, $eventArgs);
|
||||
}
|
||||
if ($parent && !empty($parent->namedNativeQueries)) {
|
||||
$this->addInheritedNamedNativeQueries($class, $parent);
|
||||
}
|
||||
|
||||
// Verify & complete identifier mapping
|
||||
if ( ! $class->identifier && ! $class->isMappedSuperclass) {
|
||||
throw MappingException::identifierRequired($className);
|
||||
}
|
||||
if ($parent && !empty($parent->sqlResultSetMappings)) {
|
||||
$this->addInheritedSqlResultSetMappings($class, $parent);
|
||||
}
|
||||
|
||||
// verify inheritance
|
||||
if (!$parent && !$class->isMappedSuperclass && !$class->isInheritanceTypeNone()) {
|
||||
$class->setParentClasses($nonSuperclassParents);
|
||||
|
||||
if ( $class->isRootEntity() && ! $class->isInheritanceTypeNone() && ! $class->discriminatorMap) {
|
||||
$this->addDefaultDiscriminatorMap($class);
|
||||
}
|
||||
|
||||
if ($this->evm->hasListeners(Events::loadClassMetadata)) {
|
||||
$eventArgs = new LoadClassMetadataEventArgs($class, $this->em);
|
||||
$this->evm->dispatchEvent(Events::loadClassMetadata, $eventArgs);
|
||||
}
|
||||
|
||||
$this->wakeupReflection($class, $this->getReflectionService());
|
||||
$this->validateRuntimeMetadata($class, $parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate runtime metadata is correctly defined.
|
||||
*
|
||||
* @param ClassMetadata $class
|
||||
* @param $parent
|
||||
* @throws MappingException
|
||||
*/
|
||||
protected function validateRuntimeMetadata($class, $parent)
|
||||
{
|
||||
if ( ! $class->reflClass ) {
|
||||
// only validate if there is a reflection class instance
|
||||
return;
|
||||
}
|
||||
|
||||
$class->validateIdentifier();
|
||||
$class->validateAssocations();
|
||||
$class->validateLifecycleCallbacks($this->getReflectionService());
|
||||
|
||||
// verify inheritance
|
||||
if ( ! $class->isMappedSuperclass && !$class->isInheritanceTypeNone()) {
|
||||
if ( ! $parent) {
|
||||
if (count($class->discriminatorMap) == 0) {
|
||||
throw MappingException::missingDiscriminatorMap($class->name);
|
||||
}
|
||||
if (!$class->discriminatorColumn) {
|
||||
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 hierarchy, otherwise problems will occur.
|
||||
throw MappingException::mappedClassNotPartOfDiscriminatorMap($class->name, $class->rootEntityName);
|
||||
}
|
||||
|
||||
$this->loadedMetadata[$className] = $class;
|
||||
|
||||
$parent = $class;
|
||||
|
||||
if ( ! $class->isMappedSuperclass) {
|
||||
array_unshift($visited, $className);
|
||||
}
|
||||
|
||||
$loaded[] = $className;
|
||||
} else if ($class->isMappedSuperclass && $class->name == $class->rootEntityName && (count($class->discriminatorMap) || $class->discriminatorColumn)) {
|
||||
// second condition is necessary for mapped superclasses in the middle of an inheritance hierarchy
|
||||
throw MappingException::noInheritanceOnMappedSuperClass($class->name);
|
||||
}
|
||||
|
||||
return $loaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new ClassMetadata instance for the given class name.
|
||||
*
|
||||
* @param string $className
|
||||
* @return Doctrine\ORM\Mapping\ClassMetadata
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function newClassMetadataInstance($className)
|
||||
{
|
||||
return new ClassMetadata($className);
|
||||
return new ClassMetadata($className, $this->em->getConfiguration()->getNamingStrategy());
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a default discriminator map if no one is given
|
||||
*
|
||||
* If an entity is of any inheritance type and does not contain a
|
||||
* discriminator map, then the map is generated automatically. This process
|
||||
* is expensive computation wise.
|
||||
*
|
||||
* The automatically generated discriminator map contains the lowercase short name of
|
||||
* each class as key.
|
||||
*
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
* @throws MappingException
|
||||
*/
|
||||
private function addDefaultDiscriminatorMap(ClassMetadata $class)
|
||||
{
|
||||
$allClasses = $this->driver->getAllClassNames();
|
||||
$fqcn = $class->getName();
|
||||
$map = array($this->getShortName($class->name) => $fqcn);
|
||||
|
||||
$duplicates = array();
|
||||
foreach ($allClasses as $subClassCandidate) {
|
||||
if (is_subclass_of($subClassCandidate, $fqcn)) {
|
||||
$shortName = $this->getShortName($subClassCandidate);
|
||||
|
||||
if (isset($map[$shortName])) {
|
||||
$duplicates[] = $shortName;
|
||||
}
|
||||
|
||||
$map[$shortName] = $subClassCandidate;
|
||||
}
|
||||
}
|
||||
|
||||
if ($duplicates) {
|
||||
throw MappingException::duplicateDiscriminatorEntry($class->name, $duplicates, $map);
|
||||
}
|
||||
|
||||
$class->setDiscriminatorMap($map);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the lower-case short name of a class.
|
||||
*
|
||||
* @param string $className
|
||||
* @return string
|
||||
*/
|
||||
private function getShortName($className)
|
||||
{
|
||||
if (strpos($className, "\\") === false) {
|
||||
return strtolower($className);
|
||||
}
|
||||
|
||||
$parts = explode("\\", $className);
|
||||
return strtolower(end($parts));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds inherited fields to the subclass mapping.
|
||||
*
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $subClass
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $parentClass
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $subClass
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass
|
||||
*/
|
||||
private function addInheritedFields(ClassMetadata $subClass, ClassMetadata $parentClass)
|
||||
{
|
||||
foreach ($parentClass->fieldMappings as $fieldName => $mapping) {
|
||||
foreach ($parentClass->fieldMappings as $mapping) {
|
||||
if ( ! isset($mapping['inherited']) && ! $parentClass->isMappedSuperclass) {
|
||||
$mapping['inherited'] = $parentClass->name;
|
||||
}
|
||||
@@ -376,8 +295,9 @@ class ClassMetadataFactory
|
||||
/**
|
||||
* 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
|
||||
* @throws MappingException
|
||||
*/
|
||||
private function addInheritedRelations(ClassMetadata $subClass, ClassMetadata $parentClass)
|
||||
{
|
||||
@@ -400,11 +320,83 @@ class ClassMetadataFactory
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds inherited named queries to the subclass mapping.
|
||||
*
|
||||
* @since 2.2
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $subClass
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass
|
||||
*/
|
||||
private function addInheritedNamedQueries(ClassMetadata $subClass, ClassMetadata $parentClass)
|
||||
{
|
||||
foreach ($parentClass->namedQueries as $name => $query) {
|
||||
if ( ! isset ($subClass->namedQueries[$name])) {
|
||||
$subClass->addNamedQuery(array(
|
||||
'name' => $query['name'],
|
||||
'query' => $query['query']
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds inherited named native queries to the subclass mapping.
|
||||
*
|
||||
* @since 2.3
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $subClass
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass
|
||||
*/
|
||||
private function addInheritedNamedNativeQueries(ClassMetadata $subClass, ClassMetadata $parentClass)
|
||||
{
|
||||
foreach ($parentClass->namedNativeQueries as $name => $query) {
|
||||
if ( ! isset ($subClass->namedNativeQueries[$name])) {
|
||||
$subClass->addNamedNativeQuery(array(
|
||||
'name' => $query['name'],
|
||||
'query' => $query['query'],
|
||||
'isSelfClass' => $query['isSelfClass'],
|
||||
'resultSetMapping' => $query['resultSetMapping'],
|
||||
'resultClass' => $query['isSelfClass'] ? $subClass->name : $query['resultClass'],
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds inherited sql result set mappings to the subclass mapping.
|
||||
*
|
||||
* @since 2.3
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $subClass
|
||||
* @param \Doctrine\ORM\Mapping\ClassMetadata $parentClass
|
||||
*/
|
||||
private function addInheritedSqlResultSetMappings(ClassMetadata $subClass, ClassMetadata $parentClass)
|
||||
{
|
||||
foreach ($parentClass->sqlResultSetMappings as $name => $mapping) {
|
||||
if ( ! isset ($subClass->sqlResultSetMappings[$name])) {
|
||||
$entities = array();
|
||||
foreach ($mapping['entities'] as $entity) {
|
||||
$entities[] = array(
|
||||
'fields' => $entity['fields'],
|
||||
'isSelfClass' => $entity['isSelfClass'],
|
||||
'discriminatorColumn' => $entity['discriminatorColumn'],
|
||||
'entityClass' => $entity['isSelfClass'] ? $subClass->name : $entity['entityClass'],
|
||||
);
|
||||
}
|
||||
|
||||
$subClass->addSqlResultSetMapping(array(
|
||||
'name' => $mapping['name'],
|
||||
'columns' => $mapping['columns'],
|
||||
'entities' => $entities,
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Completes the ID generator mapping. If "auto" is specified we choose the generator
|
||||
* most appropriate for the targeted database platform.
|
||||
*
|
||||
* @param Doctrine\ORM\Mapping\ClassMetadata $class
|
||||
* @param ClassMetadataInfo $class
|
||||
* @throws ORMException
|
||||
*/
|
||||
private function completeIdGeneratorMapping(ClassMetadataInfo $class)
|
||||
{
|
||||
@@ -425,35 +417,121 @@ class ClassMetadataFactory
|
||||
// For PostgreSQL IDENTITY (SERIAL) we need a sequence name. It defaults to
|
||||
// <table>_<column>_seq in PostgreSQL for SERIAL columns.
|
||||
// Not pretty but necessary and the simplest solution that currently works.
|
||||
$seqName = $this->targetPlatform instanceof Platforms\PostgreSQLPlatform ?
|
||||
$class->table['name'] . '_' . $class->columnNames[$class->identifier[0]] . '_seq' :
|
||||
null;
|
||||
$class->setIdGenerator(new \Doctrine\ORM\Id\IdentityGenerator($seqName));
|
||||
$sequenceName = null;
|
||||
|
||||
if ($this->targetPlatform instanceof Platforms\PostgreSQLPlatform) {
|
||||
$fieldName = $class->getSingleIdentifierFieldName();
|
||||
$columnName = $class->getSingleIdentifierColumnName();
|
||||
$quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
|
||||
$sequenceName = $class->getTableName() . '_' . $columnName . '_seq';
|
||||
$definition = array(
|
||||
'sequenceName' => $this->targetPlatform->fixSchemaElementName($sequenceName)
|
||||
);
|
||||
|
||||
if ($quoted) {
|
||||
$definition['quoted'] = true;
|
||||
}
|
||||
|
||||
$sequenceName = $this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->targetPlatform);
|
||||
}
|
||||
|
||||
$class->setIdGenerator(new \Doctrine\ORM\Id\IdentityGenerator($sequenceName));
|
||||
break;
|
||||
|
||||
case ClassMetadata::GENERATOR_TYPE_SEQUENCE:
|
||||
// If there is no sequence definition yet, create a default definition
|
||||
$definition = $class->sequenceGeneratorDefinition;
|
||||
|
||||
if ( ! $definition) {
|
||||
$sequenceName = $class->getTableName() . '_' . $class->getSingleIdentifierColumnName() . '_seq';
|
||||
$definition['sequenceName'] = $this->targetPlatform->fixSchemaElementName($sequenceName);
|
||||
$definition['allocationSize'] = 1;
|
||||
$definition['initialValue'] = 1;
|
||||
$fieldName = $class->getSingleIdentifierFieldName();
|
||||
$columnName = $class->getSingleIdentifierColumnName();
|
||||
$quoted = isset($class->fieldMappings[$fieldName]['quoted']) || isset($class->table['quoted']);
|
||||
$sequenceName = $class->getTableName() . '_' . $columnName . '_seq';
|
||||
$definition = array(
|
||||
'sequenceName' => $this->targetPlatform->fixSchemaElementName($sequenceName),
|
||||
'allocationSize' => 1,
|
||||
'initialValue' => 1,
|
||||
);
|
||||
|
||||
if ($quoted) {
|
||||
$definition['quoted'] = true;
|
||||
}
|
||||
|
||||
$class->setSequenceGeneratorDefinition($definition);
|
||||
}
|
||||
|
||||
$sequenceGenerator = new \Doctrine\ORM\Id\SequenceGenerator(
|
||||
$definition['sequenceName'],
|
||||
$this->em->getConfiguration()->getQuoteStrategy()->getSequenceName($definition, $class, $this->targetPlatform),
|
||||
$definition['allocationSize']
|
||||
);
|
||||
$class->setIdGenerator($sequenceGenerator);
|
||||
break;
|
||||
|
||||
case ClassMetadata::GENERATOR_TYPE_NONE:
|
||||
$class->setIdGenerator(new \Doctrine\ORM\Id\AssignedGenerator());
|
||||
break;
|
||||
|
||||
case ClassMetadata::GENERATOR_TYPE_UUID:
|
||||
$class->setIdGenerator(new \Doctrine\ORM\Id\UuidGenerator());
|
||||
break;
|
||||
|
||||
case ClassMetadata::GENERATOR_TYPE_TABLE:
|
||||
throw new ORMException("TableGenerator not yet implemented.");
|
||||
break;
|
||||
|
||||
case ClassMetadata::GENERATOR_TYPE_CUSTOM:
|
||||
$definition = $class->customGeneratorDefinition;
|
||||
if ( ! class_exists($definition['class'])) {
|
||||
throw new ORMException("Can't instantiate custom generator : " .
|
||||
$definition['class']);
|
||||
}
|
||||
$class->setIdGenerator(new $definition['class']);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ORMException("Unknown generator type: " . $class->generatorType);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function wakeupReflection(ClassMetadataInterface $class, ReflectionService $reflService)
|
||||
{
|
||||
/* @var $class ClassMetadata */
|
||||
$class->wakeupReflection($reflService);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function initializeReflection(ClassMetadataInterface $class, ReflectionService $reflService)
|
||||
{
|
||||
/* @var $class ClassMetadata */
|
||||
$class->initializeReflection($reflService);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getFqcnFromAlias($namespaceAlias, $simpleClassName)
|
||||
{
|
||||
return $this->em->getConfiguration()->getEntityNamespace($namespaceAlias) . '\\' . $simpleClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function getDriver()
|
||||
{
|
||||
return $this->driver;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function isEntity(ClassMetadataInterface $class)
|
||||
{
|
||||
return isset($class->isMappedSuperclass) && $class->isMappedSuperclass === false;
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
46
lib/Doctrine/ORM/Mapping/Column.php
Normal file
46
lib/Doctrine/ORM/Mapping/Column.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target({"PROPERTY","ANNOTATION"})
|
||||
*/
|
||||
final class Column implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $name;
|
||||
/** @var mixed */
|
||||
public $type = 'string';
|
||||
/** @var integer */
|
||||
public $length;
|
||||
/** @var integer */
|
||||
public $precision = 0; // The precision for a decimal (exact numeric) column (Applies only for decimal column)
|
||||
/** @var integer */
|
||||
public $scale = 0; // The scale for a decimal (exact numeric) column (Applies only for decimal column)
|
||||
/** @var boolean */
|
||||
public $unique = false;
|
||||
/** @var boolean */
|
||||
public $nullable = false;
|
||||
/** @var array */
|
||||
public $options = array();
|
||||
/** @var string */
|
||||
public $columnDefinition;
|
||||
}
|
||||
42
lib/Doctrine/ORM/Mapping/ColumnResult.php
Normal file
42
lib/Doctrine/ORM/Mapping/ColumnResult.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* References name of a column in the SELECT clause of a SQL query.
|
||||
* Scalar result types can be included in the query result by specifying this annotation in the metadata.
|
||||
*
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
* @since 2.3
|
||||
*
|
||||
* @Annotation
|
||||
* @Target("ANNOTATION")
|
||||
*/
|
||||
final class ColumnResult implements Annotation
|
||||
{
|
||||
|
||||
/**
|
||||
* The name of a column in the SELECT clause of a SQL query
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
}
|
||||
30
lib/Doctrine/ORM/Mapping/CustomIdGenerator.php
Normal file
30
lib/Doctrine/ORM/Mapping/CustomIdGenerator.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("PROPERTY")
|
||||
*/
|
||||
final class CustomIdGenerator implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $class;
|
||||
}
|
||||
86
lib/Doctrine/ORM/Mapping/DefaultNamingStrategy.php
Normal file
86
lib/Doctrine/ORM/Mapping/DefaultNamingStrategy.php
Normal file
@@ -0,0 +1,86 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* The default NamingStrategy
|
||||
*
|
||||
*
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.3
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
*/
|
||||
class DefaultNamingStrategy implements NamingStrategy
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function classToTableName($className)
|
||||
{
|
||||
if (strpos($className, '\\') !== false) {
|
||||
return substr($className, strrpos($className, '\\') + 1);
|
||||
}
|
||||
|
||||
return $className;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function propertyToColumnName($propertyName)
|
||||
{
|
||||
return $propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function referenceColumnName()
|
||||
{
|
||||
return 'id';
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function joinColumnName($propertyName)
|
||||
{
|
||||
return $propertyName . '_' . $this->referenceColumnName();
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function joinTableName($sourceEntity, $targetEntity, $propertyName = null)
|
||||
{
|
||||
return strtolower($this->classToTableName($sourceEntity) . '_' .
|
||||
$this->classToTableName($targetEntity));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function joinKeyColumnName($entityName, $referencedColumnName = null)
|
||||
{
|
||||
return strtolower($this->classToTableName($entityName) . '_' .
|
||||
($referencedColumnName ?: $this->referenceColumnName()));
|
||||
}
|
||||
}
|
||||
140
lib/Doctrine/ORM/Mapping/DefaultQuoteStrategy.php
Normal file
140
lib/Doctrine/ORM/Mapping/DefaultQuoteStrategy.php
Normal file
@@ -0,0 +1,140 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadata;
|
||||
use Doctrine\DBAL\Platforms\AbstractPlatform;
|
||||
|
||||
/**
|
||||
* A set of rules for determining the physical column, alias and table quotes
|
||||
*
|
||||
* @since 2.3
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
*/
|
||||
class DefaultQuoteStrategy implements QuoteStrategy
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getColumnName($fieldName, ClassMetadata $class, AbstractPlatform $platform)
|
||||
{
|
||||
return isset($class->fieldMappings[$fieldName]['quoted'])
|
||||
? $platform->quoteIdentifier($class->fieldMappings[$fieldName]['columnName'])
|
||||
: $class->fieldMappings[$fieldName]['columnName'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getTableName(ClassMetadata $class, AbstractPlatform $platform)
|
||||
{
|
||||
return isset($class->table['quoted'])
|
||||
? $platform->quoteIdentifier($class->table['name'])
|
||||
: $class->table['name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getSequenceName(array $definition, ClassMetadata $class, AbstractPlatform $platform)
|
||||
{
|
||||
return isset($definition['quoted'])
|
||||
? $platform->quoteIdentifier($definition['sequenceName'])
|
||||
: $definition['sequenceName'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform)
|
||||
{
|
||||
return isset($joinColumn['quoted'])
|
||||
? $platform->quoteIdentifier($joinColumn['name'])
|
||||
: $joinColumn['name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getReferencedJoinColumnName(array $joinColumn, ClassMetadata $class, AbstractPlatform $platform)
|
||||
{
|
||||
return isset($joinColumn['quoted'])
|
||||
? $platform->quoteIdentifier($joinColumn['referencedColumnName'])
|
||||
: $joinColumn['referencedColumnName'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getJoinTableName(array $association, ClassMetadata $class, AbstractPlatform $platform)
|
||||
{
|
||||
return isset($association['joinTable']['quoted'])
|
||||
? $platform->quoteIdentifier($association['joinTable']['name'])
|
||||
: $association['joinTable']['name'];
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getIdentifierColumnNames(ClassMetadata $class, AbstractPlatform $platform)
|
||||
{
|
||||
$quotedColumnNames = array();
|
||||
|
||||
foreach ($class->identifier as $fieldName) {
|
||||
if (isset($class->fieldMappings[$fieldName])) {
|
||||
$quotedColumnNames[] = $this->getColumnName($fieldName, $class, $platform);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Association defined as Id field
|
||||
$joinColumns = $class->associationMappings[$fieldName]['joinColumns'];
|
||||
$assocQuotedColumnNames = array_map(
|
||||
function ($joinColumn) use ($platform)
|
||||
{
|
||||
return isset($joinColumn['quoted'])
|
||||
? $platform->quoteIdentifier($joinColumn['name'])
|
||||
: $joinColumn['name'];
|
||||
},
|
||||
$joinColumns
|
||||
);
|
||||
|
||||
$quotedColumnNames = array_merge($quotedColumnNames, $assocQuotedColumnNames);
|
||||
}
|
||||
|
||||
return $quotedColumnNames;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function getColumnAlias($columnName, $counter, AbstractPlatform $platform, ClassMetadata $class = null)
|
||||
{
|
||||
// Trim the column alias to the maximum identifier length of the platform.
|
||||
// If the alias is to long, characters are cut off from the beginning.
|
||||
// And strip non alphanumeric characters
|
||||
$columnName = $columnName . $counter;
|
||||
$columnName = substr($columnName, -$platform->getMaxIdentifierLength());
|
||||
$columnName = preg_replace('/[^A-Za-z0-9_]/', '', $columnName);
|
||||
|
||||
return $platform->getSQLResultCasing($columnName);
|
||||
}
|
||||
|
||||
}
|
||||
38
lib/Doctrine/ORM/Mapping/DiscriminatorColumn.php
Normal file
38
lib/Doctrine/ORM/Mapping/DiscriminatorColumn.php
Normal file
@@ -0,0 +1,38 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
final class DiscriminatorColumn implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $name;
|
||||
/** @var string */
|
||||
public $type;
|
||||
/** @var integer */
|
||||
public $length;
|
||||
/** @var mixed */
|
||||
public $fieldName; // field name used in non-object hydration (array/scalar)
|
||||
/** @var string */
|
||||
public $columnDefinition;
|
||||
}
|
||||
30
lib/Doctrine/ORM/Mapping/DiscriminatorMap.php
Normal file
30
lib/Doctrine/ORM/Mapping/DiscriminatorMap.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
final class DiscriminatorMap implements Annotation
|
||||
{
|
||||
/** @var array<string> */
|
||||
public $value;
|
||||
}
|
||||
@@ -1,210 +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\Mapping\Driver;
|
||||
|
||||
use Doctrine\ORM\Mapping\MappingException;
|
||||
|
||||
/**
|
||||
* Base driver for file-based metadata drivers.
|
||||
*
|
||||
* A file driver operates in a mode where it loads the mapping files of individual
|
||||
* classes on demand. This requires the user to adhere to the convention of 1 mapping
|
||||
* file per class and the file names of the mapping files must correspond to the full
|
||||
* class name, including namespace, with the namespace delimiters '\', replaced by dots '.'.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.com
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan H. Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
abstract class AbstractFileDriver implements Driver
|
||||
{
|
||||
/**
|
||||
* The paths where to look for mapping files.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $_paths = array();
|
||||
|
||||
/**
|
||||
* The file extension of mapping documents.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_fileExtension;
|
||||
|
||||
/**
|
||||
* Initializes a new FileDriver that looks in the given path(s) for mapping
|
||||
* documents and operates in the specified operating mode.
|
||||
*
|
||||
* @param string|array $paths One or multiple paths where mapping documents can be found.
|
||||
*/
|
||||
public function __construct($paths)
|
||||
{
|
||||
$this->addPaths((array) $paths);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append lookup paths to metadata driver.
|
||||
*
|
||||
* @param array $paths
|
||||
*/
|
||||
public function addPaths(array $paths)
|
||||
{
|
||||
$this->_paths = array_unique(array_merge($this->_paths, $paths));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the defined metadata lookup paths.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPaths()
|
||||
{
|
||||
return $this->_paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file extension used to look for mapping files under
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getFileExtension()
|
||||
{
|
||||
return $this->_fileExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the file extension used to look for mapping files under
|
||||
*
|
||||
* @param string $fileExtension The file extension to set
|
||||
* @return void
|
||||
*/
|
||||
public function setFileExtension($fileExtension)
|
||||
{
|
||||
$this->_fileExtension = $fileExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the element of schema meta data for the class from the mapping file.
|
||||
* This will lazily load the mapping file if it is not loaded yet
|
||||
*
|
||||
* @return array $element The element of schema meta data
|
||||
*/
|
||||
public function getElement($className)
|
||||
{
|
||||
$result = $this->_loadMappingFile($this->_findMappingFile($className));
|
||||
|
||||
return $result[$className];
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the class with the specified name should have its metadata loaded.
|
||||
* This is only the case if it is either mapped as an Entity or a
|
||||
* MappedSuperclass.
|
||||
*
|
||||
* @param string $className
|
||||
* @return boolean
|
||||
*/
|
||||
public function isTransient($className)
|
||||
{
|
||||
$fileName = str_replace('\\', '.', $className) . $this->_fileExtension;
|
||||
|
||||
// Check whether file exists
|
||||
foreach ((array) $this->_paths as $path) {
|
||||
if (file_exists($path . DIRECTORY_SEPARATOR . $fileName)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the names of all mapped classes known to this driver.
|
||||
*
|
||||
* @return array The names of all mapped classes known to this driver.
|
||||
*/
|
||||
public function getAllClassNames()
|
||||
{
|
||||
$classes = array();
|
||||
|
||||
if ($this->_paths) {
|
||||
foreach ((array) $this->_paths as $path) {
|
||||
if ( ! is_dir($path)) {
|
||||
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
|
||||
}
|
||||
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($path),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY
|
||||
);
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
if (($fileName = $file->getBasename($this->_fileExtension)) == $file->getBasename()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// NOTE: All files found here means classes are not transient!
|
||||
$classes[] = str_replace('.', '\\', $fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the mapping file for the class with the given name by searching
|
||||
* through the configured paths.
|
||||
*
|
||||
* @param $className
|
||||
* @return string The (absolute) file name.
|
||||
* @throws MappingException
|
||||
*/
|
||||
protected function _findMappingFile($className)
|
||||
{
|
||||
$fileName = str_replace('\\', '.', $className) . $this->_fileExtension;
|
||||
|
||||
// Check whether file exists
|
||||
foreach ((array) $this->_paths as $path) {
|
||||
if (file_exists($path . DIRECTORY_SEPARATOR . $fileName)) {
|
||||
return $path . DIRECTORY_SEPARATOR . $fileName;
|
||||
}
|
||||
}
|
||||
|
||||
throw MappingException::mappingFileNotFound($className, $fileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a mapping file with the given name and returns a map
|
||||
* from class/entity names to their corresponding elements.
|
||||
*
|
||||
* @param string $file The mapping file to load.
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function _loadMappingFile($file);
|
||||
}
|
||||
@@ -13,18 +13,18 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\Common\Cache\ArrayCache,
|
||||
Doctrine\Common\Annotations\AnnotationReader,
|
||||
Doctrine\ORM\Mapping\ClassMetadataInfo,
|
||||
Doctrine\ORM\Mapping\MappingException;
|
||||
|
||||
require __DIR__ . '/DoctrineAnnotations.php';
|
||||
use Doctrine\Common\Annotations\AnnotationReader,
|
||||
Doctrine\ORM\Mapping\MappingException,
|
||||
Doctrine\ORM\Mapping\JoinColumn,
|
||||
Doctrine\ORM\Mapping\Column,
|
||||
Doctrine\Common\Persistence\Mapping\ClassMetadata,
|
||||
Doctrine\Common\Persistence\Mapping\Driver\AnnotationDriver as AbstractAnnotationDriver;
|
||||
|
||||
/**
|
||||
* The AnnotationDriver reads the mapping metadata from docblock annotations.
|
||||
@@ -35,104 +35,53 @@ require __DIR__ . '/DoctrineAnnotations.php';
|
||||
* @author Jonathan H. Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class AnnotationDriver implements Driver
|
||||
class AnnotationDriver extends AbstractAnnotationDriver
|
||||
{
|
||||
/**
|
||||
* The AnnotationReader.
|
||||
*
|
||||
* @var AnnotationReader
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
private $_reader;
|
||||
protected $entityAnnotationClasses = array(
|
||||
'Doctrine\ORM\Mapping\Entity' => 1,
|
||||
'Doctrine\ORM\Mapping\MappedSuperclass' => 2,
|
||||
);
|
||||
|
||||
/**
|
||||
* The paths where to look for mapping files.
|
||||
*
|
||||
* @var array
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected $_paths = array();
|
||||
|
||||
/**
|
||||
* The file extension of mapping documents.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $_fileExtension = '.php';
|
||||
|
||||
/**
|
||||
* @param array
|
||||
*/
|
||||
protected $_classNames;
|
||||
|
||||
/**
|
||||
* Initializes a new AnnotationDriver that uses the given AnnotationReader for reading
|
||||
* docblock annotations.
|
||||
*
|
||||
* @param $reader The AnnotationReader to use.
|
||||
* @param string|array $paths One or multiple paths where mapping classes can be found.
|
||||
*/
|
||||
public function __construct(AnnotationReader $reader, $paths = null)
|
||||
{
|
||||
$this->_reader = $reader;
|
||||
if ($paths) {
|
||||
$this->addPaths((array) $paths);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Append lookup paths to metadata driver.
|
||||
*
|
||||
* @param array $paths
|
||||
*/
|
||||
public function addPaths(array $paths)
|
||||
{
|
||||
$this->_paths = array_unique(array_merge($this->_paths, $paths));
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the defined metadata lookup paths.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function getPaths()
|
||||
{
|
||||
return $this->_paths;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the file extension used to look for mapping files under
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function getFileExtension()
|
||||
{
|
||||
return $this->_fileExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the file extension used to look for mapping files under
|
||||
*
|
||||
* @param string $fileExtension The file extension to set
|
||||
* @return void
|
||||
*/
|
||||
public function setFileExtension($fileExtension)
|
||||
{
|
||||
$this->_fileExtension = $fileExtension;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadMetadataForClass($className, ClassMetadataInfo $metadata)
|
||||
public function loadMetadataForClass($className, ClassMetadata $metadata)
|
||||
{
|
||||
/* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */
|
||||
$class = $metadata->getReflectionClass();
|
||||
if ( ! $class) {
|
||||
// this happens when running annotation driver in combination with
|
||||
// static reflection services. This is not the nicest fix
|
||||
$class = new \ReflectionClass($metadata->name);
|
||||
}
|
||||
|
||||
$classAnnotations = $this->_reader->getClassAnnotations($class);
|
||||
$classAnnotations = $this->reader->getClassAnnotations($class);
|
||||
|
||||
if ($classAnnotations) {
|
||||
foreach ($classAnnotations as $key => $annot) {
|
||||
if ( ! is_numeric($key)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$classAnnotations[get_class($annot)] = $annot;
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate Entity annotation
|
||||
if (isset($classAnnotations['Doctrine\ORM\Mapping\Entity'])) {
|
||||
$entityAnnot = $classAnnotations['Doctrine\ORM\Mapping\Entity'];
|
||||
$metadata->setCustomRepositoryClass($entityAnnot->repositoryClass);
|
||||
if ($entityAnnot->repositoryClass !== null) {
|
||||
$metadata->setCustomRepositoryClass($entityAnnot->repositoryClass);
|
||||
}
|
||||
if ($entityAnnot->readOnly) {
|
||||
$metadata->markReadOnly();
|
||||
}
|
||||
} else if (isset($classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'])) {
|
||||
$mappedSuperclassAnnot = $classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass'];
|
||||
$metadata->setCustomRepositoryClass($mappedSuperclassAnnot->repositoryClass);
|
||||
$metadata->isMappedSuperclass = true;
|
||||
} else {
|
||||
throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
|
||||
@@ -148,23 +97,106 @@ class AnnotationDriver implements Driver
|
||||
|
||||
if ($tableAnnot->indexes !== null) {
|
||||
foreach ($tableAnnot->indexes as $indexAnnot) {
|
||||
$primaryTable['indexes'][$indexAnnot->name] = array(
|
||||
'columns' => $indexAnnot->columns
|
||||
);
|
||||
$index = array('columns' => $indexAnnot->columns);
|
||||
|
||||
if ( ! empty($indexAnnot->name)) {
|
||||
$primaryTable['indexes'][$indexAnnot->name] = $index;
|
||||
} else {
|
||||
$primaryTable['indexes'][] = $index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($tableAnnot->uniqueConstraints !== null) {
|
||||
foreach ($tableAnnot->uniqueConstraints as $uniqueConstraint) {
|
||||
$primaryTable['uniqueConstraints'][$uniqueConstraint->name] = array(
|
||||
'columns' => $uniqueConstraint->columns
|
||||
);
|
||||
foreach ($tableAnnot->uniqueConstraints as $uniqueConstraintAnnot) {
|
||||
$uniqueConstraint = array('columns' => $uniqueConstraintAnnot->columns);
|
||||
|
||||
if ( ! empty($uniqueConstraintAnnot->name)) {
|
||||
$primaryTable['uniqueConstraints'][$uniqueConstraintAnnot->name] = $uniqueConstraint;
|
||||
} else {
|
||||
$primaryTable['uniqueConstraints'][] = $uniqueConstraint;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($tableAnnot->options !== null) {
|
||||
$primaryTable['options'] = $tableAnnot->options;
|
||||
}
|
||||
|
||||
$metadata->setPrimaryTable($primaryTable);
|
||||
}
|
||||
|
||||
// Evaluate NamedNativeQueries annotation
|
||||
if (isset($classAnnotations['Doctrine\ORM\Mapping\NamedNativeQueries'])) {
|
||||
$namedNativeQueriesAnnot = $classAnnotations['Doctrine\ORM\Mapping\NamedNativeQueries'];
|
||||
|
||||
foreach ($namedNativeQueriesAnnot->value as $namedNativeQuery) {
|
||||
$metadata->addNamedNativeQuery(array(
|
||||
'name' => $namedNativeQuery->name,
|
||||
'query' => $namedNativeQuery->query,
|
||||
'resultClass' => $namedNativeQuery->resultClass,
|
||||
'resultSetMapping' => $namedNativeQuery->resultSetMapping,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate SqlResultSetMappings annotation
|
||||
if (isset($classAnnotations['Doctrine\ORM\Mapping\SqlResultSetMappings'])) {
|
||||
$sqlResultSetMappingsAnnot = $classAnnotations['Doctrine\ORM\Mapping\SqlResultSetMappings'];
|
||||
|
||||
foreach ($sqlResultSetMappingsAnnot->value as $resultSetMapping) {
|
||||
$entities = array();
|
||||
$columns = array();
|
||||
foreach ($resultSetMapping->entities as $entityResultAnnot) {
|
||||
$entityResult = array(
|
||||
'fields' => array(),
|
||||
'entityClass' => $entityResultAnnot->entityClass,
|
||||
'discriminatorColumn' => $entityResultAnnot->discriminatorColumn,
|
||||
);
|
||||
|
||||
foreach ($entityResultAnnot->fields as $fieldResultAnnot) {
|
||||
$entityResult['fields'][] = array(
|
||||
'name' => $fieldResultAnnot->name,
|
||||
'column' => $fieldResultAnnot->column
|
||||
);
|
||||
}
|
||||
|
||||
$entities[] = $entityResult;
|
||||
}
|
||||
|
||||
foreach ($resultSetMapping->columns as $columnResultAnnot) {
|
||||
$columns[] = array(
|
||||
'name' => $columnResultAnnot->name,
|
||||
);
|
||||
}
|
||||
|
||||
$metadata->addSqlResultSetMapping(array(
|
||||
'name' => $resultSetMapping->name,
|
||||
'entities' => $entities,
|
||||
'columns' => $columns
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate NamedQueries annotation
|
||||
if (isset($classAnnotations['Doctrine\ORM\Mapping\NamedQueries'])) {
|
||||
$namedQueriesAnnot = $classAnnotations['Doctrine\ORM\Mapping\NamedQueries'];
|
||||
|
||||
if ( ! is_array($namedQueriesAnnot->value)) {
|
||||
throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations.");
|
||||
}
|
||||
|
||||
foreach ($namedQueriesAnnot->value as $namedQuery) {
|
||||
if ( ! ($namedQuery instanceof \Doctrine\ORM\Mapping\NamedQuery)) {
|
||||
throw new \UnexpectedValueException("@NamedQueries should contain an array of @NamedQuery annotations.");
|
||||
}
|
||||
$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'];
|
||||
@@ -177,7 +209,8 @@ class AnnotationDriver implements Driver
|
||||
$metadata->setDiscriminatorColumn(array(
|
||||
'name' => $discrColumnAnnot->name,
|
||||
'type' => $discrColumnAnnot->type,
|
||||
'length' => $discrColumnAnnot->length
|
||||
'length' => $discrColumnAnnot->length,
|
||||
'columnDefinition' => $discrColumnAnnot->columnDefinition
|
||||
));
|
||||
} else {
|
||||
$metadata->setDiscriminatorColumn(array('name' => 'dtype', 'type' => 'string', 'length' => 255));
|
||||
@@ -199,6 +232,7 @@ class AnnotationDriver implements Driver
|
||||
}
|
||||
|
||||
// Evaluate annotations on properties/fields
|
||||
/* @var $property \ReflectionProperty */
|
||||
foreach ($class->getProperties() as $property) {
|
||||
if ($metadata->isMappedSuperclass && ! $property->isPrivate()
|
||||
||
|
||||
@@ -214,138 +248,103 @@ class AnnotationDriver implements Driver
|
||||
// Check for JoinColummn/JoinColumns annotations
|
||||
$joinColumns = array();
|
||||
|
||||
if ($joinColumnAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumn')) {
|
||||
$joinColumns[] = array(
|
||||
'name' => $joinColumnAnnot->name,
|
||||
'referencedColumnName' => $joinColumnAnnot->referencedColumnName,
|
||||
'unique' => $joinColumnAnnot->unique,
|
||||
'nullable' => $joinColumnAnnot->nullable,
|
||||
'onDelete' => $joinColumnAnnot->onDelete,
|
||||
'onUpdate' => $joinColumnAnnot->onUpdate,
|
||||
'columnDefinition' => $joinColumnAnnot->columnDefinition,
|
||||
);
|
||||
} else if ($joinColumnsAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumns')) {
|
||||
if ($joinColumnAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumn')) {
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumnAnnot);
|
||||
} else if ($joinColumnsAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinColumns')) {
|
||||
foreach ($joinColumnsAnnot->value as $joinColumn) {
|
||||
$joinColumns[] = array(
|
||||
'name' => $joinColumn->name,
|
||||
'referencedColumnName' => $joinColumn->referencedColumnName,
|
||||
'unique' => $joinColumn->unique,
|
||||
'nullable' => $joinColumn->nullable,
|
||||
'onDelete' => $joinColumn->onDelete,
|
||||
'onUpdate' => $joinColumn->onUpdate,
|
||||
'columnDefinition' => $joinColumn->columnDefinition,
|
||||
);
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumn);
|
||||
}
|
||||
}
|
||||
|
||||
// Field can only be annotated with one of:
|
||||
// @Column, @OneToOne, @OneToMany, @ManyToOne, @ManyToMany
|
||||
if ($columnAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Column')) {
|
||||
if ($columnAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Column')) {
|
||||
if ($columnAnnot->type == null) {
|
||||
throw MappingException::propertyTypeIsRequired($className, $property->getName());
|
||||
}
|
||||
|
||||
$mapping['type'] = $columnAnnot->type;
|
||||
$mapping['length'] = $columnAnnot->length;
|
||||
$mapping['precision'] = $columnAnnot->precision;
|
||||
$mapping['scale'] = $columnAnnot->scale;
|
||||
$mapping['nullable'] = $columnAnnot->nullable;
|
||||
$mapping['unique'] = $columnAnnot->unique;
|
||||
if ($columnAnnot->options) {
|
||||
$mapping['options'] = $columnAnnot->options;
|
||||
}
|
||||
$mapping = $this->columnToArray($property->getName(), $columnAnnot);
|
||||
|
||||
if (isset($columnAnnot->name)) {
|
||||
$mapping['columnName'] = $columnAnnot->name;
|
||||
}
|
||||
|
||||
if (isset($columnAnnot->columnDefinition)) {
|
||||
$mapping['columnDefinition'] = $columnAnnot->columnDefinition;
|
||||
}
|
||||
|
||||
if ($idAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
|
||||
if ($idAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Id')) {
|
||||
$mapping['id'] = true;
|
||||
}
|
||||
|
||||
if ($generatedValueAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\GeneratedValue')) {
|
||||
if ($generatedValueAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\GeneratedValue')) {
|
||||
$metadata->setIdGeneratorType(constant('Doctrine\ORM\Mapping\ClassMetadata::GENERATOR_TYPE_' . $generatedValueAnnot->strategy));
|
||||
}
|
||||
|
||||
if ($versionAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Version')) {
|
||||
if ($this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\Version')) {
|
||||
$metadata->setVersionMapping($mapping);
|
||||
}
|
||||
|
||||
$metadata->mapField($mapping);
|
||||
|
||||
// Check for SequenceGenerator/TableGenerator definition
|
||||
if ($seqGeneratorAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\SequenceGenerator')) {
|
||||
if ($seqGeneratorAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\SequenceGenerator')) {
|
||||
$metadata->setSequenceGeneratorDefinition(array(
|
||||
'sequenceName' => $seqGeneratorAnnot->sequenceName,
|
||||
'allocationSize' => $seqGeneratorAnnot->allocationSize,
|
||||
'initialValue' => $seqGeneratorAnnot->initialValue
|
||||
));
|
||||
} else if ($tblGeneratorAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\TableGenerator')) {
|
||||
} else if ($this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\TableGenerator')) {
|
||||
throw MappingException::tableIdGeneratorNotImplemented($className);
|
||||
} else if ($customGeneratorAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\CustomIdGenerator')) {
|
||||
$metadata->setCustomGeneratorDefinition(array(
|
||||
'class' => $customGeneratorAnnot->class
|
||||
));
|
||||
}
|
||||
} else if ($oneToOneAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OneToOne')) {
|
||||
} 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;
|
||||
$mapping['inversedBy'] = $oneToOneAnnot->inversedBy;
|
||||
$mapping['cascade'] = $oneToOneAnnot->cascade;
|
||||
$mapping['orphanRemoval'] = $oneToOneAnnot->orphanRemoval;
|
||||
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $oneToOneAnnot->fetch);
|
||||
$mapping['fetch'] = $this->getFetchMode($className, $oneToOneAnnot->fetch);
|
||||
$metadata->mapOneToOne($mapping);
|
||||
} else if ($oneToManyAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OneToMany')) {
|
||||
} else if ($oneToManyAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OneToMany')) {
|
||||
$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);
|
||||
$mapping['fetch'] = $this->getFetchMode($className, $oneToManyAnnot->fetch);
|
||||
|
||||
if ($orderByAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
|
||||
if ($orderByAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
|
||||
$mapping['orderBy'] = $orderByAnnot->value;
|
||||
}
|
||||
|
||||
$metadata->mapOneToMany($mapping);
|
||||
} else if ($manyToOneAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToOne')) {
|
||||
} 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;
|
||||
$mapping['targetEntity'] = $manyToOneAnnot->targetEntity;
|
||||
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToOneAnnot->fetch);
|
||||
$mapping['fetch'] = $this->getFetchMode($className, $manyToOneAnnot->fetch);
|
||||
$metadata->mapManyToOne($mapping);
|
||||
} else if ($manyToManyAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToMany')) {
|
||||
} else if ($manyToManyAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\ManyToMany')) {
|
||||
$joinTable = array();
|
||||
|
||||
if ($joinTableAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinTable')) {
|
||||
if ($joinTableAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\JoinTable')) {
|
||||
$joinTable = array(
|
||||
'name' => $joinTableAnnot->name,
|
||||
'schema' => $joinTableAnnot->schema
|
||||
);
|
||||
|
||||
foreach ($joinTableAnnot->joinColumns as $joinColumn) {
|
||||
$joinTable['joinColumns'][] = array(
|
||||
'name' => $joinColumn->name,
|
||||
'referencedColumnName' => $joinColumn->referencedColumnName,
|
||||
'unique' => $joinColumn->unique,
|
||||
'nullable' => $joinColumn->nullable,
|
||||
'onDelete' => $joinColumn->onDelete,
|
||||
'onUpdate' => $joinColumn->onUpdate,
|
||||
'columnDefinition' => $joinColumn->columnDefinition,
|
||||
);
|
||||
$joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn);
|
||||
}
|
||||
|
||||
foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) {
|
||||
$joinTable['inverseJoinColumns'][] = array(
|
||||
'name' => $joinColumn->name,
|
||||
'referencedColumnName' => $joinColumn->referencedColumnName,
|
||||
'unique' => $joinColumn->unique,
|
||||
'nullable' => $joinColumn->nullable,
|
||||
'onDelete' => $joinColumn->onDelete,
|
||||
'onUpdate' => $joinColumn->onUpdate,
|
||||
'columnDefinition' => $joinColumn->columnDefinition,
|
||||
);
|
||||
$joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,9 +353,11 @@ class AnnotationDriver implements Driver
|
||||
$mapping['mappedBy'] = $manyToManyAnnot->mappedBy;
|
||||
$mapping['inversedBy'] = $manyToManyAnnot->inversedBy;
|
||||
$mapping['cascade'] = $manyToManyAnnot->cascade;
|
||||
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $manyToManyAnnot->fetch);
|
||||
$mapping['indexBy'] = $manyToManyAnnot->indexBy;
|
||||
$mapping['orphanRemoval'] = $manyToManyAnnot->orphanRemoval;
|
||||
$mapping['fetch'] = $this->getFetchMode($className, $manyToManyAnnot->fetch);
|
||||
|
||||
if ($orderByAnnot = $this->_reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
|
||||
if ($orderByAnnot = $this->reader->getPropertyAnnotation($property, 'Doctrine\ORM\Mapping\OrderBy')) {
|
||||
$mapping['orderBy'] = $orderByAnnot->value;
|
||||
}
|
||||
|
||||
@@ -364,12 +365,72 @@ class AnnotationDriver implements Driver
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate AssociationOverrides annotation
|
||||
if (isset($classAnnotations['Doctrine\ORM\Mapping\AssociationOverrides'])) {
|
||||
$associationOverridesAnnot = $classAnnotations['Doctrine\ORM\Mapping\AssociationOverrides'];
|
||||
|
||||
foreach ($associationOverridesAnnot->value as $associationOverride) {
|
||||
$override = array();
|
||||
$fieldName = $associationOverride->name;
|
||||
|
||||
// Check for JoinColummn/JoinColumns annotations
|
||||
if ($associationOverride->joinColumns) {
|
||||
$joinColumns = array();
|
||||
foreach ($associationOverride->joinColumns as $joinColumn) {
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumn);
|
||||
}
|
||||
$override['joinColumns'] = $joinColumns;
|
||||
}
|
||||
|
||||
// Check for JoinTable annotations
|
||||
if ($associationOverride->joinTable) {
|
||||
$joinTable = null;
|
||||
$joinTableAnnot = $associationOverride->joinTable;
|
||||
$joinTable = array(
|
||||
'name' => $joinTableAnnot->name,
|
||||
'schema' => $joinTableAnnot->schema
|
||||
);
|
||||
|
||||
foreach ($joinTableAnnot->joinColumns as $joinColumn) {
|
||||
$joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumn);
|
||||
}
|
||||
|
||||
foreach ($joinTableAnnot->inverseJoinColumns as $joinColumn) {
|
||||
$joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumn);
|
||||
}
|
||||
|
||||
$override['joinTable'] = $joinTable;
|
||||
}
|
||||
|
||||
$metadata->setAssociationOverride($fieldName, $override);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate AttributeOverrides annotation
|
||||
if (isset($classAnnotations['Doctrine\ORM\Mapping\AttributeOverrides'])) {
|
||||
$attributeOverridesAnnot = $classAnnotations['Doctrine\ORM\Mapping\AttributeOverrides'];
|
||||
foreach ($attributeOverridesAnnot->value as $attributeOverrideAnnot) {
|
||||
$attributeOverride = $this->columnToArray($attributeOverrideAnnot->name, $attributeOverrideAnnot->column);
|
||||
$metadata->setAttributeOverride($attributeOverrideAnnot->name, $attributeOverride);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate @HasLifecycleCallbacks annotation
|
||||
if (isset($classAnnotations['Doctrine\ORM\Mapping\HasLifecycleCallbacks'])) {
|
||||
/* @var $method \ReflectionMethod */
|
||||
foreach ($class->getMethods() as $method) {
|
||||
// filter for the declaring class only, callbacks from parents will already be registered.
|
||||
if ($method->isPublic() && $method->getDeclaringClass()->getName() == $class->name) {
|
||||
$annotations = $this->_reader->getMethodAnnotations($method);
|
||||
$annotations = $this->reader->getMethodAnnotations($method);
|
||||
|
||||
if ($annotations) {
|
||||
foreach ($annotations as $key => $annot) {
|
||||
if ( ! is_numeric($key)) {
|
||||
continue;
|
||||
}
|
||||
$annotations[get_class($annot)] = $annot;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($annotations['Doctrine\ORM\Mapping\PrePersist'])) {
|
||||
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::prePersist);
|
||||
@@ -398,83 +459,87 @@ class AnnotationDriver implements Driver
|
||||
if (isset($annotations['Doctrine\ORM\Mapping\PostLoad'])) {
|
||||
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::postLoad);
|
||||
}
|
||||
|
||||
if (isset($annotations['Doctrine\ORM\Mapping\PreFlush'])) {
|
||||
$metadata->addLifecycleCallback($method->getName(), \Doctrine\ORM\Events::preFlush);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the class with the specified name is transient. Only non-transient
|
||||
* classes, that is entities and mapped superclasses, should have their metadata loaded.
|
||||
* A class is non-transient if it is annotated with either @Entity or
|
||||
* @MappedSuperclass in the class doc block.
|
||||
* Attempts to resolve the fetch mode.
|
||||
*
|
||||
* @param string $className
|
||||
* @return boolean
|
||||
* @param string $className The class name
|
||||
* @param string $fetchMode The fetch mode
|
||||
* @return integer The fetch mode as defined in ClassMetadata
|
||||
* @throws MappingException If the fetch mode is not valid
|
||||
*/
|
||||
public function isTransient($className)
|
||||
private function getFetchMode($className, $fetchMode)
|
||||
{
|
||||
$classAnnotations = $this->_reader->getClassAnnotations(new \ReflectionClass($className));
|
||||
if( ! defined('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode)) {
|
||||
throw MappingException::invalidFetchMode($className, $fetchMode);
|
||||
}
|
||||
|
||||
return ! isset($classAnnotations['Doctrine\ORM\Mapping\Entity']) &&
|
||||
! isset($classAnnotations['Doctrine\ORM\Mapping\MappedSuperclass']);
|
||||
return constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . $fetchMode);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* Parse the given JoinColumn as array
|
||||
*
|
||||
* @param JoinColumn $joinColumn
|
||||
* @return array
|
||||
*/
|
||||
public function getAllClassNames()
|
||||
private function joinColumnToArray(JoinColumn $joinColumn)
|
||||
{
|
||||
if ($this->_classNames !== null) {
|
||||
return $this->_classNames;
|
||||
return array(
|
||||
'name' => $joinColumn->name,
|
||||
'unique' => $joinColumn->unique,
|
||||
'nullable' => $joinColumn->nullable,
|
||||
'onDelete' => $joinColumn->onDelete,
|
||||
'columnDefinition' => $joinColumn->columnDefinition,
|
||||
'referencedColumnName' => $joinColumn->referencedColumnName,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given Column as array
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param Column $column
|
||||
* @return array
|
||||
*/
|
||||
private function columnToArray($fieldName, Column $column)
|
||||
{
|
||||
$mapping = array(
|
||||
'fieldName' => $fieldName,
|
||||
'type' => $column->type,
|
||||
'scale' => $column->scale,
|
||||
'length' => $column->length,
|
||||
'unique' => $column->unique,
|
||||
'nullable' => $column->nullable,
|
||||
'precision' => $column->precision
|
||||
);
|
||||
|
||||
if ($column->options) {
|
||||
$mapping['options'] = $column->options;
|
||||
}
|
||||
|
||||
if (!$this->_paths) {
|
||||
throw MappingException::pathRequired();
|
||||
if (isset($column->name)) {
|
||||
$mapping['columnName'] = $column->name;
|
||||
}
|
||||
|
||||
$classes = array();
|
||||
$includedFiles = array();
|
||||
|
||||
foreach ($this->_paths as $path) {
|
||||
if ( ! is_dir($path)) {
|
||||
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
|
||||
}
|
||||
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($path),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY
|
||||
);
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
if (($fileName = $file->getBasename($this->_fileExtension)) == $file->getBasename()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sourceFile = realpath($file->getPathName());
|
||||
require_once $sourceFile;
|
||||
$includedFiles[] = $sourceFile;
|
||||
}
|
||||
if (isset($column->columnDefinition)) {
|
||||
$mapping['columnDefinition'] = $column->columnDefinition;
|
||||
}
|
||||
|
||||
$declared = get_declared_classes();
|
||||
|
||||
foreach ($declared as $className) {
|
||||
$rc = new \ReflectionClass($className);
|
||||
$sourceFile = $rc->getFileName();
|
||||
if (in_array($sourceFile, $includedFiles) && ! $this->isTransient($className)) {
|
||||
$classes[] = $className;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_classNames = $classes;
|
||||
|
||||
return $classes;
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Factory method for the Annotation Driver
|
||||
*
|
||||
*
|
||||
* @param array|string $paths
|
||||
* @param AnnotationReader $reader
|
||||
* @return AnnotationDriver
|
||||
@@ -483,8 +548,8 @@ class AnnotationDriver implements Driver
|
||||
{
|
||||
if ($reader == null) {
|
||||
$reader = new AnnotationReader();
|
||||
$reader->setDefaultAnnotationNamespace('Doctrine\ORM\Mapping\\');
|
||||
}
|
||||
|
||||
return new self($reader, $paths);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,31 +13,31 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\Common\Cache\ArrayCache,
|
||||
Doctrine\Common\Annotations\AnnotationReader,
|
||||
Doctrine\DBAL\Schema\AbstractSchemaManager,
|
||||
use Doctrine\DBAL\Schema\AbstractSchemaManager,
|
||||
Doctrine\DBAL\Schema\SchemaException,
|
||||
Doctrine\Common\Persistence\Mapping\Driver\MappingDriver,
|
||||
Doctrine\Common\Persistence\Mapping\ClassMetadata,
|
||||
Doctrine\ORM\Mapping\ClassMetadataInfo,
|
||||
Doctrine\ORM\Mapping\MappingException,
|
||||
Doctrine\Common\Util\Inflector;
|
||||
Doctrine\Common\Util\Inflector,
|
||||
Doctrine\ORM\Mapping\MappingException;
|
||||
|
||||
/**
|
||||
* The DatabaseDriver reverse engineers the mapping metadata from a database.
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
*
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan Wage <jonwage@gmail.com>
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
*/
|
||||
class DatabaseDriver implements Driver
|
||||
class DatabaseDriver implements MappingDriver
|
||||
{
|
||||
/**
|
||||
* @var AbstractSchemaManager
|
||||
@@ -55,31 +55,68 @@ class DatabaseDriver implements Driver
|
||||
* @var array
|
||||
*/
|
||||
private $manyToManyTables = array();
|
||||
|
||||
|
||||
/**
|
||||
* Initializes a new AnnotationDriver that uses the given AnnotationReader for reading
|
||||
* docblock annotations.
|
||||
*
|
||||
* @param AnnotationReader $reader The AnnotationReader to use.
|
||||
* @var array
|
||||
*/
|
||||
private $classNamesForTables = array();
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $fieldNamesForColumns = array();
|
||||
|
||||
/**
|
||||
* The namespace for the generated entities.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $namespace;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param AbstractSchemaManager $schemaManager
|
||||
*/
|
||||
public function __construct(AbstractSchemaManager $schemaManager)
|
||||
{
|
||||
$this->_sm = $schemaManager;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set tables manually instead of relying on the reverse engeneering capabilities of SchemaManager.
|
||||
*
|
||||
* @param array $entityTables
|
||||
* @param array $manyToManyTables
|
||||
* @return void
|
||||
*/
|
||||
public function setTables($entityTables, $manyToManyTables)
|
||||
{
|
||||
$this->tables = $this->manyToManyTables = $this->classToTableNames = array();
|
||||
foreach ($entityTables as $table) {
|
||||
$className = $this->getClassNameForTable($table->getName());
|
||||
$this->classToTableNames[$className] = $table->getName();
|
||||
$this->tables[$table->getName()] = $table;
|
||||
}
|
||||
foreach ($manyToManyTables as $table) {
|
||||
$this->manyToManyTables[$table->getName()] = $table;
|
||||
}
|
||||
}
|
||||
|
||||
private function reverseEngineerMappingFromDatabase()
|
||||
{
|
||||
if ($this->tables !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$tables = array();
|
||||
|
||||
foreach ($this->_sm->listTableNames() as $tableName) {
|
||||
$tables[$tableName] = $this->_sm->listTableDetails($tableName);
|
||||
}
|
||||
|
||||
$this->tables = array();
|
||||
foreach ($tables AS $tableName => $table) {
|
||||
/* @var $table Table */
|
||||
$this->tables = $this->manyToManyTables = $this->classToTableNames = array();
|
||||
foreach ($tables as $tableName => $table) {
|
||||
/* @var $table \Doctrine\DBAL\Schema\Table */
|
||||
if ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
|
||||
$foreignKeys = $table->getForeignKeys();
|
||||
} else {
|
||||
@@ -87,34 +124,37 @@ class DatabaseDriver implements Driver
|
||||
}
|
||||
|
||||
$allForeignKeyColumns = array();
|
||||
foreach ($foreignKeys AS $foreignKey) {
|
||||
foreach ($foreignKeys as $foreignKey) {
|
||||
$allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns());
|
||||
}
|
||||
|
||||
|
||||
if ( ! $table->hasPrimaryKey()) {
|
||||
throw new MappingException(
|
||||
"Table " . $table->getName() . " has no primary key. Doctrine does not ".
|
||||
"support reverse engineering from tables that don't have a primary key."
|
||||
);
|
||||
}
|
||||
|
||||
$pkColumns = $table->getPrimaryKey()->getColumns();
|
||||
sort($pkColumns);
|
||||
sort($allForeignKeyColumns);
|
||||
|
||||
if ($pkColumns == $allForeignKeyColumns) {
|
||||
if (count($table->getForeignKeys()) > 2) {
|
||||
throw new \InvalidArgumentException("ManyToMany table '" . $tableName . "' with more or less than two foreign keys are not supported by the Database Reverese Engineering Driver.");
|
||||
}
|
||||
|
||||
if ($pkColumns == $allForeignKeyColumns && count($foreignKeys) == 2) {
|
||||
$this->manyToManyTables[$tableName] = $table;
|
||||
} else {
|
||||
// lower-casing is necessary because of Oracle Uppercase Tablenames,
|
||||
// assumption is lower-case + underscore separated.
|
||||
$className = Inflector::classify(strtolower($tableName));
|
||||
$className = $this->getClassNameForTable($tableName);
|
||||
$this->tables[$tableName] = $table;
|
||||
$this->classToTableNames[$className] = $tableName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadMetadataForClass($className, ClassMetadataInfo $metadata)
|
||||
public function loadMetadataForClass($className, ClassMetadata $metadata)
|
||||
{
|
||||
$this->reverseEngineerMappingFromDatabase();
|
||||
|
||||
@@ -134,7 +174,7 @@ class DatabaseDriver implements Driver
|
||||
} catch(SchemaException $e) {
|
||||
$primaryKeyColumns = array();
|
||||
}
|
||||
|
||||
|
||||
if ($this->_sm->getDatabasePlatform()->supportsForeignKeyConstraints()) {
|
||||
$foreignKeys = $this->tables[$tableName]->getForeignKeys();
|
||||
} else {
|
||||
@@ -142,7 +182,7 @@ class DatabaseDriver implements Driver
|
||||
}
|
||||
|
||||
$allForeignKeyColumns = array();
|
||||
foreach ($foreignKeys AS $foreignKey) {
|
||||
foreach ($foreignKeys as $foreignKey) {
|
||||
$allForeignKeyColumns = array_merge($allForeignKeyColumns, $foreignKey->getLocalColumns());
|
||||
}
|
||||
|
||||
@@ -150,13 +190,14 @@ class DatabaseDriver implements Driver
|
||||
$fieldMappings = array();
|
||||
foreach ($columns as $column) {
|
||||
$fieldMapping = array();
|
||||
if ($primaryKeyColumns && in_array($column->getName(), $primaryKeyColumns)) {
|
||||
$fieldMapping['id'] = true;
|
||||
} else if (in_array($column->getName(), $allForeignKeyColumns)) {
|
||||
|
||||
if (in_array($column->getName(), $allForeignKeyColumns)) {
|
||||
continue;
|
||||
} else if ($primaryKeyColumns && in_array($column->getName(), $primaryKeyColumns)) {
|
||||
$fieldMapping['id'] = true;
|
||||
}
|
||||
|
||||
$fieldMapping['fieldName'] = Inflector::camelize(strtolower($column->getName()));
|
||||
$fieldMapping['fieldName'] = $this->getFieldNameForColumn($tableName, $column->getName(), false);
|
||||
$fieldMapping['columnName'] = $column->getName();
|
||||
$fieldMapping['type'] = strtolower((string) $column->getType());
|
||||
|
||||
@@ -189,23 +230,31 @@ class DatabaseDriver implements Driver
|
||||
$metadata->mapField($fieldMapping);
|
||||
}
|
||||
|
||||
foreach ($this->manyToManyTables AS $manyTable) {
|
||||
foreach ($manyTable->getForeignKeys() AS $foreignKey) {
|
||||
foreach ($this->manyToManyTables as $manyTable) {
|
||||
foreach ($manyTable->getForeignKeys() as $foreignKey) {
|
||||
// foreign key maps to the table of the current entity, many to many association probably exists
|
||||
if (strtolower($tableName) == strtolower($foreignKey->getForeignTableName())) {
|
||||
$myFk = $foreignKey;
|
||||
foreach ($manyTable->getForeignKeys() AS $foreignKey) {
|
||||
$otherFk = null;
|
||||
foreach ($manyTable->getForeignKeys() as $foreignKey) {
|
||||
if ($foreignKey != $myFk) {
|
||||
$otherFk = $foreignKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!$otherFk) {
|
||||
// the definition of this many to many table does not contain
|
||||
// enough foreign key information to continue reverse engeneering.
|
||||
continue;
|
||||
}
|
||||
|
||||
$localColumn = current($myFk->getColumns());
|
||||
$associationMapping = array();
|
||||
$associationMapping['fieldName'] = Inflector::camelize(str_replace('_id', '', strtolower(current($otherFk->getColumns()))));
|
||||
$associationMapping['targetEntity'] = Inflector::classify(strtolower($otherFk->getForeignTableName()));
|
||||
$associationMapping['fieldName'] = $this->getFieldNameForColumn($manyTable->getName(), current($otherFk->getColumns()), true);
|
||||
$associationMapping['targetEntity'] = $this->getClassNameForTable($otherFk->getForeignTableName());
|
||||
if (current($manyTable->getColumns())->getName() == $localColumn) {
|
||||
$associationMapping['inversedBy'] = Inflector::camelize(str_replace('_id', '', strtolower(current($myFk->getColumns()))));
|
||||
$associationMapping['inversedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getColumns()), true);
|
||||
$associationMapping['joinTable'] = array(
|
||||
'name' => strtolower($manyTable->getName()),
|
||||
'joinColumns' => array(),
|
||||
@@ -230,7 +279,7 @@ class DatabaseDriver implements Driver
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$associationMapping['mappedBy'] = Inflector::camelize(str_replace('_id', '', strtolower(current($myFk->getColumns()))));
|
||||
$associationMapping['mappedBy'] = $this->getFieldNameForColumn($manyTable->getName(), current($myFk->getColumns()), true);
|
||||
}
|
||||
$metadata->mapManyToMany($associationMapping);
|
||||
break;
|
||||
@@ -245,8 +294,12 @@ class DatabaseDriver implements Driver
|
||||
|
||||
$localColumn = current($cols);
|
||||
$associationMapping = array();
|
||||
$associationMapping['fieldName'] = Inflector::camelize(str_replace('_id', '', strtolower($localColumn)));
|
||||
$associationMapping['targetEntity'] = Inflector::classify($foreignTable);
|
||||
$associationMapping['fieldName'] = $this->getFieldNameForColumn($tableName, $localColumn, true);
|
||||
$associationMapping['targetEntity'] = $this->getClassNameForTable($foreignTable);
|
||||
|
||||
if ($primaryKeyColumns && in_array($localColumn, $primaryKeyColumns)) {
|
||||
$associationMapping['id'] = true;
|
||||
}
|
||||
|
||||
for ($i = 0; $i < count($cols); $i++) {
|
||||
$associationMapping['joinColumns'][] = array(
|
||||
@@ -254,12 +307,18 @@ class DatabaseDriver implements Driver
|
||||
'referencedColumnName' => $fkCols[$i],
|
||||
);
|
||||
}
|
||||
$metadata->mapManyToOne($associationMapping);
|
||||
|
||||
//Here we need to check if $cols are the same as $primaryKeyColums
|
||||
if (!array_diff($cols,$primaryKeyColumns)) {
|
||||
$metadata->mapOneToOne($associationMapping);
|
||||
} else {
|
||||
$metadata->mapManyToOne($associationMapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function isTransient($className)
|
||||
{
|
||||
@@ -267,11 +326,7 @@ class DatabaseDriver implements Driver
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all the class names supported by this driver.
|
||||
*
|
||||
* IMPORTANT: This method must return an array of class not tables names.
|
||||
*
|
||||
* @return array
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function getAllClassNames()
|
||||
{
|
||||
@@ -279,4 +334,78 @@ 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,7 +1,5 @@
|
||||
<?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
|
||||
@@ -15,123 +13,54 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
use Doctrine\Common\Annotations\Annotation;
|
||||
|
||||
/* Annotations */
|
||||
|
||||
final class Entity extends Annotation {
|
||||
public $repositoryClass;
|
||||
}
|
||||
final class MappedSuperclass extends Annotation {}
|
||||
final class InheritanceType extends Annotation {}
|
||||
final class DiscriminatorColumn extends Annotation {
|
||||
public $name;
|
||||
public $fieldName; // field name used in non-object hydration (array/scalar)
|
||||
public $type;
|
||||
public $length;
|
||||
}
|
||||
final class DiscriminatorMap extends Annotation {}
|
||||
final class Id extends Annotation {}
|
||||
final class GeneratedValue extends Annotation {
|
||||
public $strategy = 'AUTO';
|
||||
}
|
||||
final class Version extends Annotation {}
|
||||
final class JoinColumn extends Annotation {
|
||||
public $name;
|
||||
public $fieldName; // field name used in non-object hydration (array/scalar)
|
||||
public $referencedColumnName = 'id';
|
||||
public $unique = false;
|
||||
public $nullable = true;
|
||||
public $onDelete;
|
||||
public $onUpdate;
|
||||
public $columnDefinition;
|
||||
}
|
||||
final class JoinColumns extends Annotation {}
|
||||
final class Column extends Annotation {
|
||||
public $type = 'string';
|
||||
public $length;
|
||||
// The precision for a decimal (exact numeric) column (Applies only for decimal column)
|
||||
public $precision = 0;
|
||||
// The scale for a decimal (exact numeric) column (Applies only for decimal column)
|
||||
public $scale = 0;
|
||||
public $unique = false;
|
||||
public $nullable = false;
|
||||
public $name;
|
||||
public $options = array();
|
||||
public $columnDefinition;
|
||||
}
|
||||
final class OneToOne extends Annotation {
|
||||
public $targetEntity;
|
||||
public $mappedBy;
|
||||
public $inversedBy;
|
||||
public $cascade;
|
||||
public $fetch = 'LAZY';
|
||||
public $orphanRemoval = false;
|
||||
}
|
||||
final class OneToMany extends Annotation {
|
||||
public $mappedBy;
|
||||
public $targetEntity;
|
||||
public $cascade;
|
||||
public $fetch = 'LAZY';
|
||||
public $orphanRemoval = false;
|
||||
}
|
||||
final class ManyToOne extends Annotation {
|
||||
public $targetEntity;
|
||||
public $cascade;
|
||||
public $fetch = 'LAZY';
|
||||
public $inversedBy;
|
||||
}
|
||||
final class ManyToMany extends Annotation {
|
||||
public $targetEntity;
|
||||
public $mappedBy;
|
||||
public $inversedBy;
|
||||
public $cascade;
|
||||
public $fetch = 'LAZY';
|
||||
}
|
||||
final class ElementCollection extends Annotation {
|
||||
public $tableName;
|
||||
}
|
||||
final class Table extends Annotation {
|
||||
public $name;
|
||||
public $schema;
|
||||
public $indexes;
|
||||
public $uniqueConstraints;
|
||||
}
|
||||
final class UniqueConstraint extends Annotation {
|
||||
public $name;
|
||||
public $columns;
|
||||
}
|
||||
final class Index extends Annotation {
|
||||
public $name;
|
||||
public $columns;
|
||||
}
|
||||
final class JoinTable extends Annotation {
|
||||
public $name;
|
||||
public $schema;
|
||||
public $joinColumns = array();
|
||||
public $inverseJoinColumns = array();
|
||||
}
|
||||
final class SequenceGenerator extends Annotation {
|
||||
public $sequenceName;
|
||||
public $allocationSize = 1;
|
||||
public $initialValue = 1;
|
||||
}
|
||||
final class ChangeTrackingPolicy extends Annotation {}
|
||||
final class OrderBy extends Annotation {}
|
||||
|
||||
/* Annotations for lifecycle callbacks */
|
||||
final class HasLifecycleCallbacks extends Annotation {}
|
||||
final class PrePersist extends Annotation {}
|
||||
final class PostPersist extends Annotation {}
|
||||
final class PreUpdate extends Annotation {}
|
||||
final class PostUpdate extends Annotation {}
|
||||
final class PreRemove extends Annotation {}
|
||||
final class PostRemove extends Annotation {}
|
||||
final class PostLoad extends Annotation {}
|
||||
|
||||
require_once __DIR__.'/../Annotation.php';
|
||||
require_once __DIR__.'/../Entity.php';
|
||||
require_once __DIR__.'/../MappedSuperclass.php';
|
||||
require_once __DIR__.'/../InheritanceType.php';
|
||||
require_once __DIR__.'/../DiscriminatorColumn.php';
|
||||
require_once __DIR__.'/../DiscriminatorMap.php';
|
||||
require_once __DIR__.'/../Id.php';
|
||||
require_once __DIR__.'/../GeneratedValue.php';
|
||||
require_once __DIR__.'/../Version.php';
|
||||
require_once __DIR__.'/../JoinColumn.php';
|
||||
require_once __DIR__.'/../JoinColumns.php';
|
||||
require_once __DIR__.'/../Column.php';
|
||||
require_once __DIR__.'/../OneToOne.php';
|
||||
require_once __DIR__.'/../OneToMany.php';
|
||||
require_once __DIR__.'/../ManyToOne.php';
|
||||
require_once __DIR__.'/../ManyToMany.php';
|
||||
require_once __DIR__.'/../ElementCollection.php';
|
||||
require_once __DIR__.'/../Table.php';
|
||||
require_once __DIR__.'/../UniqueConstraint.php';
|
||||
require_once __DIR__.'/../Index.php';
|
||||
require_once __DIR__.'/../JoinTable.php';
|
||||
require_once __DIR__.'/../SequenceGenerator.php';
|
||||
require_once __DIR__.'/../CustomIdGenerator.php';
|
||||
require_once __DIR__.'/../ChangeTrackingPolicy.php';
|
||||
require_once __DIR__.'/../OrderBy.php';
|
||||
require_once __DIR__.'/../NamedQueries.php';
|
||||
require_once __DIR__.'/../NamedQuery.php';
|
||||
require_once __DIR__.'/../HasLifecycleCallbacks.php';
|
||||
require_once __DIR__.'/../PrePersist.php';
|
||||
require_once __DIR__.'/../PostPersist.php';
|
||||
require_once __DIR__.'/../PreUpdate.php';
|
||||
require_once __DIR__.'/../PostUpdate.php';
|
||||
require_once __DIR__.'/../PreRemove.php';
|
||||
require_once __DIR__.'/../PostRemove.php';
|
||||
require_once __DIR__.'/../PostLoad.php';
|
||||
require_once __DIR__.'/../PreFlush.php';
|
||||
require_once __DIR__.'/../FieldResult.php';
|
||||
require_once __DIR__.'/../ColumnResult.php';
|
||||
require_once __DIR__.'/../EntityResult.php';
|
||||
require_once __DIR__.'/../NamedNativeQuery.php';
|
||||
require_once __DIR__.'/../NamedNativeQueries.php';
|
||||
require_once __DIR__.'/../SqlResultSetMapping.php';
|
||||
require_once __DIR__.'/../SqlResultSetMappings.php';
|
||||
require_once __DIR__.'/../AssociationOverride.php';
|
||||
require_once __DIR__.'/../AssociationOverrides.php';
|
||||
require_once __DIR__.'/../AttributeOverride.php';
|
||||
require_once __DIR__.'/../AttributeOverrides.php';
|
||||
|
||||
@@ -13,109 +13,19 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\ORM\Mapping\Driver\Driver,
|
||||
Doctrine\ORM\Mapping\ClassMetadataInfo,
|
||||
Doctrine\ORM\Mapping\MappingException;
|
||||
use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain;
|
||||
|
||||
/**
|
||||
* The DriverChain allows you to add multiple other mapping drivers for
|
||||
* certain namespaces
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @since 2.0
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan H. Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @todo Rename: MappingDriverChain or MetadataDriverChain
|
||||
* @deprecated this driver will be removed. Use Doctrine\Common\Persistence\Mapping\Driver\MappingDriverChain instead
|
||||
*/
|
||||
class DriverChain implements Driver
|
||||
class DriverChain extends MappingDriverChain
|
||||
{
|
||||
/**
|
||||
* @var array
|
||||
*/
|
||||
private $_drivers = array();
|
||||
|
||||
/**
|
||||
* Add a nested driver.
|
||||
*
|
||||
* @param Driver $nestedDriver
|
||||
* @param string $namespace
|
||||
*/
|
||||
public function addDriver(Driver $nestedDriver, $namespace)
|
||||
{
|
||||
$this->_drivers[$namespace] = $nestedDriver;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the array of nested drivers.
|
||||
*
|
||||
* @return array $drivers
|
||||
*/
|
||||
public function getDrivers()
|
||||
{
|
||||
return $this->_drivers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the metadata for the specified class into the provided container.
|
||||
*
|
||||
* @param string $className
|
||||
* @param ClassMetadataInfo $metadata
|
||||
*/
|
||||
public function loadMetadataForClass($className, ClassMetadataInfo $metadata)
|
||||
{
|
||||
foreach ($this->_drivers as $namespace => $driver) {
|
||||
if (strpos($className, $namespace) === 0) {
|
||||
$driver->loadMetadataForClass($className, $metadata);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the names of all mapped classes known to this driver.
|
||||
*
|
||||
* @return array The names of all mapped classes known to this driver.
|
||||
*/
|
||||
public function getAllClassNames()
|
||||
{
|
||||
$classNames = array();
|
||||
foreach ($this->_drivers AS $namespace => $driver) {
|
||||
$driverClasses = $driver->getAllClassNames();
|
||||
foreach ($driverClasses AS $className) {
|
||||
if (strpos($className, $namespace) === 0) {
|
||||
$classNames[] = $className;
|
||||
}
|
||||
}
|
||||
}
|
||||
return array_unique($classNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether the class with the specified name should have its metadata loaded.
|
||||
*
|
||||
* This is only the case for non-transient classes either mapped as an Entity or MappedSuperclass.
|
||||
*
|
||||
* @param string $className
|
||||
* @return boolean
|
||||
*/
|
||||
public function isTransient($className)
|
||||
{
|
||||
foreach ($this->_drivers AS $namespace => $driver) {
|
||||
if (strpos($className, $namespace) === 0) {
|
||||
return $driver->isTransient($className);
|
||||
}
|
||||
}
|
||||
|
||||
// class isTransient, i.e. not an entity or mapped superclass
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -13,57 +13,19 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\Common\Cache\ArrayCache,
|
||||
Doctrine\Common\Annotations\AnnotationReader,
|
||||
Doctrine\DBAL\Schema\AbstractSchemaManager,
|
||||
Doctrine\ORM\Mapping\ClassMetadataInfo,
|
||||
Doctrine\ORM\Mapping\MappingException,
|
||||
Doctrine\Common\Util\Inflector,
|
||||
Doctrine\ORM\Mapping\Driver\AbstractFileDriver;
|
||||
use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver as CommonPHPDriver;
|
||||
|
||||
/**
|
||||
* The PHPDriver includes php files which just populate ClassMetadataInfo
|
||||
* instances with plain php code
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan H. Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @todo Rename: PHPDriver
|
||||
* @deprecated this driver will be removed. Use Doctrine\Common\Persistence\Mapping\Driver\PHPDriver instead
|
||||
*/
|
||||
class PHPDriver extends AbstractFileDriver
|
||||
class PHPDriver extends CommonPHPDriver
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $_fileExtension = '.php';
|
||||
protected $_metadata;
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadMetadataForClass($className, ClassMetadataInfo $metadata)
|
||||
{
|
||||
$this->_metadata = $metadata;
|
||||
$this->_loadMappingFile($this->_findMappingFile($className));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected function _loadMappingFile($file)
|
||||
{
|
||||
$metadata = $this->_metadata;
|
||||
include $file;
|
||||
}
|
||||
}
|
||||
43
lib/Doctrine/ORM/Mapping/Driver/SimplifiedXmlDriver.php
Normal file
43
lib/Doctrine/ORM/Mapping/Driver/SimplifiedXmlDriver.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator;
|
||||
|
||||
/**
|
||||
* XmlDriver that additionally looks for mapping information in a global file.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @license MIT
|
||||
*/
|
||||
class SimplifiedXmlDriver extends XmlDriver
|
||||
{
|
||||
const DEFAULT_FILE_EXTENSION = '.orm.xml';
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function __construct($prefixes, $fileExtension = self::DEFAULT_FILE_EXTENSION)
|
||||
{
|
||||
$locator = new SymfonyFileLocator((array) $prefixes, $fileExtension);
|
||||
parent::__construct($locator, $fileExtension);
|
||||
}
|
||||
}
|
||||
43
lib/Doctrine/ORM/Mapping/Driver/SimplifiedYamlDriver.php
Normal file
43
lib/Doctrine/ORM/Mapping/Driver/SimplifiedYamlDriver.php
Normal file
@@ -0,0 +1,43 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\Common\Persistence\Mapping\Driver\SymfonyFileLocator;
|
||||
|
||||
/**
|
||||
* YamlDriver that additionally looks for mapping information in a global file.
|
||||
*
|
||||
* @author Fabien Potencier <fabien@symfony.com>
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @license MIT
|
||||
*/
|
||||
class SimplifiedYamlDriver extends YamlDriver
|
||||
{
|
||||
const DEFAULT_FILE_EXTENSION = '.orm.yml';
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function __construct($prefixes, $fileExtension = self::DEFAULT_FILE_EXTENSION)
|
||||
{
|
||||
$locator = new SymfonyFileLocator((array) $prefixes, $fileExtension);
|
||||
parent::__construct($locator, $fileExtension);
|
||||
}
|
||||
}
|
||||
@@ -13,126 +13,19 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadataInfo,
|
||||
Doctrine\ORM\Mapping\MappingException;
|
||||
use Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver as CommonStaticPHPDriver;
|
||||
|
||||
/**
|
||||
* The StaticPHPDriver calls a static loadMetadata() method on your entity
|
||||
* classes where you can manually populate the ClassMetadata instance.
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @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 H. Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
* @deprecated this driver will be removed. Use Doctrine\Common\Persistence\Mapping\Driver\StaticPHPDriver instead
|
||||
*/
|
||||
class StaticPHPDriver implements Driver
|
||||
class StaticPHPDriver extends CommonStaticPHPDriver
|
||||
{
|
||||
/**
|
||||
* Paths of entity directories.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_paths = array();
|
||||
|
||||
/**
|
||||
* Map of all class names.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $_classNames;
|
||||
|
||||
/**
|
||||
* The file extension of mapping documents.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $_fileExtension = '.php';
|
||||
|
||||
public function __construct($paths)
|
||||
{
|
||||
$this->addPaths((array) $paths);
|
||||
}
|
||||
|
||||
public function addPaths(array $paths)
|
||||
{
|
||||
$this->_paths = array_unique(array_merge($this->_paths, $paths));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function loadMetadataForClass($className, ClassMetadataInfo $metadata)
|
||||
{
|
||||
call_user_func_array(array($className, 'loadMetadata'), array($metadata));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @todo Same code exists in AnnotationDriver, should we re-use it somehow or not worry about it?
|
||||
*/
|
||||
public function getAllClassNames()
|
||||
{
|
||||
if ($this->_classNames !== null) {
|
||||
return $this->_classNames;
|
||||
}
|
||||
|
||||
if (!$this->_paths) {
|
||||
throw MappingException::pathRequired();
|
||||
}
|
||||
|
||||
$classes = array();
|
||||
$includedFiles = array();
|
||||
|
||||
foreach ($this->_paths as $path) {
|
||||
if (!is_dir($path)) {
|
||||
throw MappingException::fileMappingDriversRequireConfiguredDirectoryPath($path);
|
||||
}
|
||||
|
||||
$iterator = new \RecursiveIteratorIterator(
|
||||
new \RecursiveDirectoryIterator($path),
|
||||
\RecursiveIteratorIterator::LEAVES_ONLY
|
||||
);
|
||||
|
||||
foreach ($iterator as $file) {
|
||||
if (($fileName = $file->getBasename($this->_fileExtension)) == $file->getBasename()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$sourceFile = realpath($file->getPathName());
|
||||
require_once $sourceFile;
|
||||
$includedFiles[] = $sourceFile;
|
||||
}
|
||||
}
|
||||
|
||||
$declared = get_declared_classes();
|
||||
|
||||
foreach ($declared as $className) {
|
||||
$rc = new \ReflectionClass($className);
|
||||
$sourceFile = $rc->getFileName();
|
||||
if (in_array($sourceFile, $includedFiles) && !$this->isTransient($className)) {
|
||||
$classes[] = $className;
|
||||
}
|
||||
}
|
||||
|
||||
$this->_classNames = $classes;
|
||||
|
||||
return $classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public function isTransient($className)
|
||||
{
|
||||
return method_exists($className, 'loadMetadata') ? false : true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,5 @@
|
||||
<?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
|
||||
@@ -15,14 +13,15 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use SimpleXMLElement,
|
||||
Doctrine\ORM\Mapping\ClassMetadataInfo,
|
||||
Doctrine\Common\Persistence\Mapping\Driver\FileDriver,
|
||||
Doctrine\Common\Persistence\Mapping\ClassMetadata,
|
||||
Doctrine\ORM\Mapping\MappingException;
|
||||
|
||||
/**
|
||||
@@ -31,31 +30,43 @@ use SimpleXMLElement,
|
||||
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.0
|
||||
* @version $Revision$
|
||||
* @author Benjamin Eberlei <kontakt@beberlei.de>
|
||||
* @author Guilherme Blanco <guilhermeblanco@hotmail.com>
|
||||
* @author Jonathan H. Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class XmlDriver extends AbstractFileDriver
|
||||
class XmlDriver extends FileDriver
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $_fileExtension = '.dcm.xml';
|
||||
const DEFAULT_FILE_EXTENSION = '.dcm.xml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadMetadataForClass($className, ClassMetadataInfo $metadata)
|
||||
public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION)
|
||||
{
|
||||
parent::__construct($locator, $fileExtension);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadMetadataForClass($className, ClassMetadata $metadata)
|
||||
{
|
||||
/* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */
|
||||
/* @var $xmlRoot SimpleXMLElement */
|
||||
$xmlRoot = $this->getElement($className);
|
||||
|
||||
if ($xmlRoot->getName() == 'entity') {
|
||||
if (isset($xmlRoot['repository-class'])) {
|
||||
$metadata->setCustomRepositoryClass((string)$xmlRoot['repository-class']);
|
||||
}
|
||||
if (isset($xmlRoot['read-only']) && $xmlRoot['read-only'] == "true") {
|
||||
$metadata->markReadOnly();
|
||||
}
|
||||
} else if ($xmlRoot->getName() == 'mapped-superclass') {
|
||||
$metadata->setCustomRepositoryClass(
|
||||
isset($xmlRoot['repository-class']) ? (string)$xmlRoot['repository-class'] : null
|
||||
);
|
||||
} else if ($xmlRoot->getName() == 'mapped-superclass') {
|
||||
$metadata->isMappedSuperclass = true;
|
||||
} else {
|
||||
throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
|
||||
@@ -69,11 +80,73 @@ 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']
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate native named queries
|
||||
if (isset($xmlRoot->{'named-native-queries'})) {
|
||||
foreach ($xmlRoot->{'named-native-queries'}->{'named-native-query'} as $nativeQueryElement) {
|
||||
$metadata->addNamedNativeQuery(array(
|
||||
'name' => isset($nativeQueryElement['name']) ? (string)$nativeQueryElement['name'] : null,
|
||||
'query' => isset($nativeQueryElement->query) ? (string)$nativeQueryElement->query : null,
|
||||
'resultClass' => isset($nativeQueryElement['result-class']) ? (string)$nativeQueryElement['result-class'] : null,
|
||||
'resultSetMapping' => isset($nativeQueryElement['result-set-mapping']) ? (string)$nativeQueryElement['result-set-mapping'] : null,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate sql result set mapping
|
||||
if (isset($xmlRoot->{'sql-result-set-mappings'})) {
|
||||
foreach ($xmlRoot->{'sql-result-set-mappings'}->{'sql-result-set-mapping'} as $rsmElement) {
|
||||
$entities = array();
|
||||
$columns = array();
|
||||
foreach ($rsmElement as $entityElement) {
|
||||
//<entity-result/>
|
||||
if (isset($entityElement['entity-class'])) {
|
||||
$entityResult = array(
|
||||
'fields' => array(),
|
||||
'entityClass' => (string)$entityElement['entity-class'],
|
||||
'discriminatorColumn' => isset($entityElement['discriminator-column']) ? (string)$entityElement['discriminator-column'] : null,
|
||||
);
|
||||
|
||||
foreach ($entityElement as $fieldElement) {
|
||||
$entityResult['fields'][] = array(
|
||||
'name' => isset($fieldElement['name']) ? (string)$fieldElement['name'] : null,
|
||||
'column' => isset($fieldElement['column']) ? (string)$fieldElement['column'] : null,
|
||||
);
|
||||
}
|
||||
|
||||
$entities[] = $entityResult;
|
||||
}
|
||||
|
||||
//<column-result/>
|
||||
if (isset($entityElement['name'])) {
|
||||
$columns[] = array(
|
||||
'name' => (string)$entityElement['name'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$metadata->addSqlResultSetMapping(array(
|
||||
'name' => (string)$rsmElement['name'],
|
||||
'entities' => $entities,
|
||||
'columns' => $columns
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/* 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));
|
||||
@@ -83,9 +156,10 @@ class XmlDriver extends AbstractFileDriver
|
||||
if (isset($xmlRoot->{'discriminator-column'})) {
|
||||
$discrColumn = $xmlRoot->{'discriminator-column'};
|
||||
$metadata->setDiscriminatorColumn(array(
|
||||
'name' => (string)$discrColumn['name'],
|
||||
'type' => (string)$discrColumn['type'],
|
||||
'length' => (string)$discrColumn['length']
|
||||
'name' => isset($discrColumn['name']) ? (string)$discrColumn['name'] : null,
|
||||
'type' => isset($discrColumn['type']) ? (string)$discrColumn['type'] : null,
|
||||
'length' => isset($discrColumn['length']) ? (string)$discrColumn['length'] : null,
|
||||
'columnDefinition' => isset($discrColumn['column-definition']) ? (string)$discrColumn['column-definition'] : null
|
||||
));
|
||||
} else {
|
||||
$metadata->setDiscriminatorColumn(array('name' => 'dtype', 'type' => 'string', 'length' => 255));
|
||||
@@ -94,7 +168,7 @@ class XmlDriver extends AbstractFileDriver
|
||||
// Evaluate <discriminator-map...>
|
||||
if (isset($xmlRoot->{'discriminator-map'})) {
|
||||
$map = array();
|
||||
foreach ($xmlRoot->{'discriminator-map'}->{'discriminator-mapping'} AS $discrMapElement) {
|
||||
foreach ($xmlRoot->{'discriminator-map'}->{'discriminator-mapping'} as $discrMapElement) {
|
||||
$map[(string)$discrMapElement['value']] = (string)$discrMapElement['class'];
|
||||
}
|
||||
$metadata->setDiscriminatorMap($map);
|
||||
@@ -145,66 +219,54 @@ class XmlDriver extends AbstractFileDriver
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($xmlRoot->options)) {
|
||||
$metadata->table['options'] = $this->_parseOptions($xmlRoot->options->children());
|
||||
}
|
||||
|
||||
// The mapping assignement is done in 2 times as a bug might occurs on some php/xml lib versions
|
||||
// The internal SimpleXmlIterator get resetted, to this generate a duplicate field exception
|
||||
$mappings = array();
|
||||
// Evaluate <field ...> mappings
|
||||
if (isset($xmlRoot->field)) {
|
||||
foreach ($xmlRoot->field as $fieldMapping) {
|
||||
$mapping = array(
|
||||
'fieldName' => (string)$fieldMapping['name'],
|
||||
'type' => (string)$fieldMapping['type']
|
||||
);
|
||||
|
||||
if (isset($fieldMapping['column'])) {
|
||||
$mapping['columnName'] = (string)$fieldMapping['column'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['length'])) {
|
||||
$mapping['length'] = (int)$fieldMapping['length'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['precision'])) {
|
||||
$mapping['precision'] = (int)$fieldMapping['precision'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['scale'])) {
|
||||
$mapping['scale'] = (int)$fieldMapping['scale'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['unique'])) {
|
||||
$mapping['unique'] = ((string)$fieldMapping['unique'] == "false") ? false : true;
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['options'])) {
|
||||
$mapping['options'] = (array)$fieldMapping['options'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['nullable'])) {
|
||||
$mapping['nullable'] = ((string)$fieldMapping['nullable'] == "false") ? false : true;
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['version']) && $fieldMapping['version']) {
|
||||
$metadata->setVersionMapping($mapping);
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['column-definition'])) {
|
||||
$mapping['columnDefinition'] = (string)$fieldMapping['column-definition'];
|
||||
}
|
||||
|
||||
$mapping = $this->columnToArray($fieldMapping);
|
||||
$metadata->mapField($mapping);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($mappings as $mapping) {
|
||||
$metadata->mapField($mapping);
|
||||
}
|
||||
|
||||
// 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'],
|
||||
'type' => (string)$idElement['type']
|
||||
'fieldName' => (string)$idElement['name']
|
||||
);
|
||||
|
||||
if (isset($idElement['type'])) {
|
||||
$mapping['type'] = (string)$idElement['type'];
|
||||
}
|
||||
|
||||
if (isset($idElement['length'])) {
|
||||
$mapping['length'] = (string)$idElement['length'];
|
||||
}
|
||||
|
||||
if (isset($idElement['column'])) {
|
||||
$mapping['columnName'] = (string)$idElement['column'];
|
||||
}
|
||||
|
||||
if (isset($idElement['column-definition'])) {
|
||||
$mapping['columnDefinition'] = (string)$idElement['column-definition'];
|
||||
}
|
||||
|
||||
$metadata->mapField($mapping);
|
||||
|
||||
if (isset($idElement->generator)) {
|
||||
@@ -222,6 +284,11 @@ class XmlDriver extends AbstractFileDriver
|
||||
'allocationSize' => (string)$seqGenerator['allocation-size'],
|
||||
'initialValue' => (string)$seqGenerator['initial-value']
|
||||
));
|
||||
} else if (isset($idElement->{'custom-id-generator'})) {
|
||||
$customGenerator = $idElement->{'custom-id-generator'};
|
||||
$metadata->setCustomGeneratorDefinition(array(
|
||||
'class' => (string) $customGenerator['class']
|
||||
));
|
||||
} else if (isset($idElement->{'table-generator'})) {
|
||||
throw MappingException::tableIdGeneratorNotImplemented($className);
|
||||
}
|
||||
@@ -235,6 +302,10 @@ 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']);
|
||||
}
|
||||
@@ -248,10 +319,10 @@ class XmlDriver extends AbstractFileDriver
|
||||
$joinColumns = array();
|
||||
|
||||
if (isset($oneToOneElement->{'join-column'})) {
|
||||
$joinColumns[] = $this->_getJoinColumnMapping($oneToOneElement->{'join-column'});
|
||||
$joinColumns[] = $this->joinColumnToArray($oneToOneElement->{'join-column'});
|
||||
} else if (isset($oneToOneElement->{'join-columns'})) {
|
||||
foreach ($oneToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
|
||||
$joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement);
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,8 +333,8 @@ class XmlDriver extends AbstractFileDriver
|
||||
$mapping['cascade'] = $this->_getCascadeMappings($oneToOneElement->cascade);
|
||||
}
|
||||
|
||||
if (isset($oneToOneElement->{'orphan-removal'})) {
|
||||
$mapping['orphanRemoval'] = (bool)$oneToOneElement->{'orphan-removal'};
|
||||
if (isset($oneToOneElement['orphan-removal'])) {
|
||||
$mapping['orphanRemoval'] = (bool)$oneToOneElement['orphan-removal'];
|
||||
}
|
||||
|
||||
$metadata->mapOneToOne($mapping);
|
||||
@@ -287,18 +358,24 @@ class XmlDriver extends AbstractFileDriver
|
||||
$mapping['cascade'] = $this->_getCascadeMappings($oneToManyElement->cascade);
|
||||
}
|
||||
|
||||
if (isset($oneToManyElement->{'orphan-removal'})) {
|
||||
$mapping['orphanRemoval'] = (bool)$oneToManyElement->{'orphan-removal'};
|
||||
if (isset($oneToManyElement['orphan-removal'])) {
|
||||
$mapping['orphanRemoval'] = (bool)$oneToManyElement['orphan-removal'];
|
||||
}
|
||||
|
||||
if (isset($oneToManyElement->{'order-by'})) {
|
||||
$orderBy = array();
|
||||
foreach ($oneToManyElement->{'order-by'}->{'order-by-field'} AS $orderByField) {
|
||||
foreach ($oneToManyElement->{'order-by'}->{'order-by-field'} as $orderByField) {
|
||||
$orderBy[(string)$orderByField['name']] = (string)$orderByField['direction'];
|
||||
}
|
||||
$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);
|
||||
}
|
||||
}
|
||||
@@ -311,6 +388,10 @@ 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']);
|
||||
}
|
||||
@@ -322,13 +403,10 @@ class XmlDriver extends AbstractFileDriver
|
||||
$joinColumns = array();
|
||||
|
||||
if (isset($manyToOneElement->{'join-column'})) {
|
||||
$joinColumns[] = $this->_getJoinColumnMapping($manyToOneElement->{'join-column'});
|
||||
$joinColumns[] = $this->joinColumnToArray($manyToOneElement->{'join-column'});
|
||||
} else if (isset($manyToOneElement->{'join-columns'})) {
|
||||
foreach ($manyToOneElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
|
||||
if (!isset($joinColumnElement['name'])) {
|
||||
$joinColumnElement['name'] = $name;
|
||||
}
|
||||
$joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement);
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -338,10 +416,6 @@ class XmlDriver extends AbstractFileDriver
|
||||
$mapping['cascade'] = $this->_getCascadeMappings($manyToOneElement->cascade);
|
||||
}
|
||||
|
||||
if (isset($manyToOneElement->{'orphan-removal'})) {
|
||||
$mapping['orphanRemoval'] = (bool)$manyToOneElement->{'orphan-removal'};
|
||||
}
|
||||
|
||||
$metadata->mapManyToOne($mapping);
|
||||
}
|
||||
}
|
||||
@@ -358,6 +432,10 @@ class XmlDriver extends AbstractFileDriver
|
||||
$mapping['fetch'] = constant('Doctrine\ORM\Mapping\ClassMetadata::FETCH_' . (string)$manyToManyElement['fetch']);
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement['orphan-removal'])) {
|
||||
$mapping['orphanRemoval'] = (bool)$manyToManyElement['orphan-removal'];
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement['mapped-by'])) {
|
||||
$mapping['mappedBy'] = (string)$manyToManyElement['mapped-by'];
|
||||
} else if (isset($manyToManyElement->{'join-table'})) {
|
||||
@@ -375,11 +453,11 @@ class XmlDriver extends AbstractFileDriver
|
||||
}
|
||||
|
||||
foreach ($joinTableElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
|
||||
$joinTable['joinColumns'][] = $this->_getJoinColumnMapping($joinColumnElement);
|
||||
$joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
|
||||
foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} as $joinColumnElement) {
|
||||
$joinTable['inverseJoinColumns'][] = $this->_getJoinColumnMapping($joinColumnElement);
|
||||
$joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
|
||||
$mapping['joinTable'] = $joinTable;
|
||||
@@ -389,22 +467,80 @@ class XmlDriver extends AbstractFileDriver
|
||||
$mapping['cascade'] = $this->_getCascadeMappings($manyToManyElement->cascade);
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement->{'orphan-removal'})) {
|
||||
$mapping['orphanRemoval'] = (bool)$manyToManyElement->{'orphan-removal'};
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement->{'order-by'})) {
|
||||
$orderBy = array();
|
||||
foreach ($manyToManyElement->{'order-by'}->{'order-by-field'} AS $orderByField) {
|
||||
foreach ($manyToManyElement->{'order-by'}->{'order-by-field'} as $orderByField) {
|
||||
$orderBy[(string)$orderByField['name']] = (string)$orderByField['direction'];
|
||||
}
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate association-overrides
|
||||
if (isset($xmlRoot->{'attribute-overrides'})) {
|
||||
foreach ($xmlRoot->{'attribute-overrides'}->{'attribute-override'} as $overrideElement) {
|
||||
$fieldName = (string) $overrideElement['name'];
|
||||
foreach ($overrideElement->field as $field) {
|
||||
$mapping = $this->columnToArray($field);
|
||||
$mapping['fieldName'] = $fieldName;
|
||||
$metadata->setAttributeOverride($fieldName, $mapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate association-overrides
|
||||
if (isset($xmlRoot->{'association-overrides'})) {
|
||||
foreach ($xmlRoot->{'association-overrides'}->{'association-override'} as $overrideElement) {
|
||||
$fieldName = (string) $overrideElement['name'];
|
||||
$override = array();
|
||||
|
||||
// Check for join-columns
|
||||
if (isset($overrideElement->{'join-columns'})) {
|
||||
$joinColumns = array();
|
||||
foreach ($overrideElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
$override['joinColumns'] = $joinColumns;
|
||||
}
|
||||
|
||||
// Check for join-table
|
||||
if ($overrideElement->{'join-table'}) {
|
||||
$joinTable = null;
|
||||
$joinTableElement = $overrideElement->{'join-table'};
|
||||
|
||||
$joinTable = array(
|
||||
'name' => (string) $joinTableElement['name'],
|
||||
'schema' => (string) $joinTableElement['schema']
|
||||
);
|
||||
|
||||
if (isset($joinTableElement->{'join-columns'})) {
|
||||
foreach ($joinTableElement->{'join-columns'}->{'join-column'} as $joinColumnElement) {
|
||||
$joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($joinTableElement->{'inverse-join-columns'})) {
|
||||
foreach ($joinTableElement->{'inverse-join-columns'}->{'join-column'} as $joinColumnElement) {
|
||||
$joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
}
|
||||
|
||||
$override['joinTable'] = $joinTable;
|
||||
}
|
||||
|
||||
$metadata->setAssociationOverride($fieldName, $override);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate <lifecycle-callbacks...>
|
||||
if (isset($xmlRoot->{'lifecycle-callbacks'})) {
|
||||
foreach ($xmlRoot->{'lifecycle-callbacks'}->{'lifecycle-callback'} as $lifecycleCallback) {
|
||||
@@ -413,14 +549,44 @@ class XmlDriver extends AbstractFileDriver
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses (nested) option elements.
|
||||
*
|
||||
* @param SimpleXMLElement $options the XML element.
|
||||
* @return array The options array.
|
||||
*/
|
||||
private function _parseOptions(SimpleXMLElement $options)
|
||||
{
|
||||
$array = array();
|
||||
|
||||
/* @var $option SimpleXMLElement */
|
||||
foreach ($options as $option) {
|
||||
if ($option->count()) {
|
||||
$value = $this->_parseOptions($option->children());
|
||||
} else {
|
||||
$value = (string) $option;
|
||||
}
|
||||
|
||||
$attr = $option->attributes();
|
||||
|
||||
if (isset($attr->name)) {
|
||||
$array[(string) $attr->name] = $value;
|
||||
} else {
|
||||
$array[] = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a joinColumn mapping array based on the information
|
||||
* found in the given SimpleXMLElement.
|
||||
*
|
||||
* @param $joinColumnElement The XML element.
|
||||
* @param SimpleXMLElement $joinColumnElement the XML element.
|
||||
* @return array The mapping array.
|
||||
*/
|
||||
private function _getJoinColumnMapping(SimpleXMLElement $joinColumnElement)
|
||||
private function joinColumnToArray(SimpleXMLElement $joinColumnElement)
|
||||
{
|
||||
$joinColumn = array(
|
||||
'name' => (string)$joinColumnElement['name'],
|
||||
@@ -439,10 +605,6 @@ class XmlDriver extends AbstractFileDriver
|
||||
$joinColumn['onDelete'] = (string)$joinColumnElement['on-delete'];
|
||||
}
|
||||
|
||||
if (isset($joinColumnElement['on-update'])) {
|
||||
$joinColumn['onUpdate'] = (string)$joinColumnElement['on-update'];
|
||||
}
|
||||
|
||||
if (isset($joinColumnElement['column-definition'])) {
|
||||
$joinColumn['columnDefinition'] = (string)$joinColumnElement['column-definition'];
|
||||
}
|
||||
@@ -450,15 +612,71 @@ class XmlDriver extends AbstractFileDriver
|
||||
return $joinColumn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given field as array
|
||||
*
|
||||
* @param SimpleXMLElement $fieldMapping
|
||||
* @return array
|
||||
*/
|
||||
private function columnToArray(SimpleXMLElement $fieldMapping)
|
||||
{
|
||||
$mapping = array(
|
||||
'fieldName' => (string) $fieldMapping['name'],
|
||||
);
|
||||
|
||||
if (isset($fieldMapping['type'])) {
|
||||
$mapping['type'] = (string) $fieldMapping['type'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['column'])) {
|
||||
$mapping['columnName'] = (string) $fieldMapping['column'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['length'])) {
|
||||
$mapping['length'] = (int) $fieldMapping['length'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['precision'])) {
|
||||
$mapping['precision'] = (int) $fieldMapping['precision'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['scale'])) {
|
||||
$mapping['scale'] = (int) $fieldMapping['scale'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['unique'])) {
|
||||
$mapping['unique'] = ((string) $fieldMapping['unique'] == "false") ? false : true;
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['nullable'])) {
|
||||
$mapping['nullable'] = ((string) $fieldMapping['nullable'] == "false") ? false : true;
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['version']) && $fieldMapping['version']) {
|
||||
$mapping['version'] = $fieldMapping['version'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping['column-definition'])) {
|
||||
$mapping['columnDefinition'] = (string) $fieldMapping['column-definition'];
|
||||
}
|
||||
|
||||
if (isset($fieldMapping->options)) {
|
||||
$mapping['options'] = $this->_parseOptions($fieldMapping->options->children());
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gathers a list of cascade options found in the given cascade element.
|
||||
*
|
||||
* @param $cascadeElement The cascade element.
|
||||
* @param SimpleXMLElement $cascadeElement the cascade element.
|
||||
* @return array The list of cascade options.
|
||||
*/
|
||||
private function _getCascadeMappings($cascadeElement)
|
||||
{
|
||||
$cascades = array();
|
||||
/* @var $action SimpleXmlElement */
|
||||
foreach ($cascadeElement->children() as $action) {
|
||||
// According to the JPA specifications, XML uses "cascade-persist"
|
||||
// instead of "persist". Here, both variations
|
||||
@@ -471,9 +689,9 @@ class XmlDriver extends AbstractFileDriver
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function _loadMappingFile($file)
|
||||
protected function loadMappingFile($file)
|
||||
{
|
||||
$result = array();
|
||||
$xmlElement = simplexml_load_file($file);
|
||||
|
||||
@@ -13,14 +13,16 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping\Driver;
|
||||
|
||||
use Doctrine\ORM\Mapping\ClassMetadataInfo,
|
||||
Doctrine\ORM\Mapping\MappingException;
|
||||
use Doctrine\Common\Persistence\Mapping\ClassMetadata,
|
||||
Doctrine\Common\Persistence\Mapping\Driver\FileDriver,
|
||||
Doctrine\ORM\Mapping\MappingException,
|
||||
Symfony\Component\Yaml\Yaml;
|
||||
|
||||
/**
|
||||
* The YamlDriver reads the mapping metadata from yaml schema files.
|
||||
@@ -31,25 +33,37 @@ use Doctrine\ORM\Mapping\ClassMetadataInfo,
|
||||
* @author Jonathan H. Wage <jonwage@gmail.com>
|
||||
* @author Roman Borschel <roman@code-factory.org>
|
||||
*/
|
||||
class YamlDriver extends AbstractFileDriver
|
||||
class YamlDriver extends FileDriver
|
||||
{
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
protected $_fileExtension = '.dcm.yml';
|
||||
const DEFAULT_FILE_EXTENSION = '.dcm.yml';
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadMetadataForClass($className, ClassMetadataInfo $metadata)
|
||||
public function __construct($locator, $fileExtension = self::DEFAULT_FILE_EXTENSION)
|
||||
{
|
||||
parent::__construct($locator, $fileExtension);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public function loadMetadataForClass($className, ClassMetadata $metadata)
|
||||
{
|
||||
/* @var $metadata \Doctrine\ORM\Mapping\ClassMetadataInfo */
|
||||
$element = $this->getElement($className);
|
||||
|
||||
if ($element['type'] == 'entity') {
|
||||
if (isset($element['repositoryClass'])) {
|
||||
$metadata->setCustomRepositoryClass($element['repositoryClass']);
|
||||
}
|
||||
if (isset($element['readOnly']) && $element['readOnly'] == true) {
|
||||
$metadata->markReadOnly();
|
||||
}
|
||||
} else if ($element['type'] == 'mappedSuperclass') {
|
||||
$metadata->setCustomRepositoryClass(
|
||||
isset($element['repositoryClass']) ? $element['repositoryClass'] : null
|
||||
);
|
||||
} else if ($element['type'] == 'mappedSuperclass') {
|
||||
$metadata->isMappedSuperclass = true;
|
||||
} else {
|
||||
throw MappingException::classIsNotAValidEntityOrMappedSuperClass($className);
|
||||
@@ -62,6 +76,83 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate named native queries
|
||||
if (isset($element['namedNativeQueries'])) {
|
||||
foreach ($element['namedNativeQueries'] as $name => $mappingElement) {
|
||||
if (!isset($mappingElement['name'])) {
|
||||
$mappingElement['name'] = $name;
|
||||
}
|
||||
$metadata->addNamedNativeQuery(array(
|
||||
'name' => $mappingElement['name'],
|
||||
'query' => isset($mappingElement['query']) ? $mappingElement['query'] : null,
|
||||
'resultClass' => isset($mappingElement['resultClass']) ? $mappingElement['resultClass'] : null,
|
||||
'resultSetMapping' => isset($mappingElement['resultSetMapping']) ? $mappingElement['resultSetMapping'] : null,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate sql result set mappings
|
||||
if (isset($element['sqlResultSetMappings'])) {
|
||||
foreach ($element['sqlResultSetMappings'] as $name => $resultSetMapping) {
|
||||
if (!isset($resultSetMapping['name'])) {
|
||||
$resultSetMapping['name'] = $name;
|
||||
}
|
||||
|
||||
$entities = array();
|
||||
$columns = array();
|
||||
if (isset($resultSetMapping['entityResult'])) {
|
||||
foreach ($resultSetMapping['entityResult'] as $entityResultElement) {
|
||||
$entityResult = array(
|
||||
'fields' => array(),
|
||||
'entityClass' => isset($entityResultElement['entityClass']) ? $entityResultElement['entityClass'] : null,
|
||||
'discriminatorColumn' => isset($entityResultElement['discriminatorColumn']) ? $entityResultElement['discriminatorColumn'] : null,
|
||||
);
|
||||
|
||||
if (isset($entityResultElement['fieldResult'])) {
|
||||
foreach ($entityResultElement['fieldResult'] as $fieldResultElement) {
|
||||
$entityResult['fields'][] = array(
|
||||
'name' => isset($fieldResultElement['name']) ? $fieldResultElement['name'] : null,
|
||||
'column' => isset($fieldResultElement['column']) ? $fieldResultElement['column'] : null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$entities[] = $entityResult;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (isset($resultSetMapping['columnResult'])) {
|
||||
foreach ($resultSetMapping['columnResult'] as $columnResultAnnot) {
|
||||
$columns[] = array(
|
||||
'name' => isset($columnResultAnnot['name']) ? $columnResultAnnot['name'] : null,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
$metadata->addSqlResultSetMapping(array(
|
||||
'name' => $resultSetMapping['name'],
|
||||
'entities' => $entities,
|
||||
'columns' => $columns
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
/* not implemented specially anyway. use table = schema.table
|
||||
if (isset($element['schema'])) {
|
||||
$metadata->table['schema'] = $element['schema'];
|
||||
@@ -75,9 +166,10 @@ class YamlDriver extends AbstractFileDriver
|
||||
if (isset($element['discriminatorColumn'])) {
|
||||
$discrColumn = $element['discriminatorColumn'];
|
||||
$metadata->setDiscriminatorColumn(array(
|
||||
'name' => $discrColumn['name'],
|
||||
'type' => $discrColumn['type'],
|
||||
'length' => $discrColumn['length']
|
||||
'name' => isset($discrColumn['name']) ? (string)$discrColumn['name'] : null,
|
||||
'type' => isset($discrColumn['type']) ? (string)$discrColumn['type'] : null,
|
||||
'length' => isset($discrColumn['length']) ? (string)$discrColumn['length'] : null,
|
||||
'columnDefinition' => isset($discrColumn['columnDefinition']) ? (string)$discrColumn['columnDefinition'] : null
|
||||
));
|
||||
} else {
|
||||
$metadata->setDiscriminatorColumn(array('name' => 'dtype', 'type' => 'string', 'length' => 255));
|
||||
@@ -135,19 +227,28 @@ class YamlDriver extends AbstractFileDriver
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($element['options'])) {
|
||||
$metadata->table['options'] = $element['options'];
|
||||
}
|
||||
|
||||
$associationIds = array();
|
||||
if (isset($element['id'])) {
|
||||
// Evaluate identifier settings
|
||||
foreach ($element['id'] as $name => $idElement) {
|
||||
if (!isset($idElement['type'])) {
|
||||
throw MappingException::propertyTypeIsRequired($className, $name);
|
||||
if (isset($idElement['associationKey']) && $idElement['associationKey'] == true) {
|
||||
$associationIds[$name] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
$mapping = array(
|
||||
'id' => true,
|
||||
'fieldName' => $name,
|
||||
'type' => $idElement['type']
|
||||
'fieldName' => $name
|
||||
);
|
||||
|
||||
if (isset($idElement['type'])) {
|
||||
$mapping['type'] = $idElement['type'];
|
||||
}
|
||||
|
||||
if (isset($idElement['column'])) {
|
||||
$mapping['columnName'] = $idElement['column'];
|
||||
}
|
||||
@@ -156,6 +257,10 @@ class YamlDriver extends AbstractFileDriver
|
||||
$mapping['length'] = $idElement['length'];
|
||||
}
|
||||
|
||||
if (isset($idElement['columnDefinition'])) {
|
||||
$mapping['columnDefinition'] = $idElement['columnDefinition'];
|
||||
}
|
||||
|
||||
$metadata->mapField($mapping);
|
||||
|
||||
if (isset($idElement['generator'])) {
|
||||
@@ -165,6 +270,11 @@ class YamlDriver extends AbstractFileDriver
|
||||
// Check for SequenceGenerator/TableGenerator definition
|
||||
if (isset($idElement['sequenceGenerator'])) {
|
||||
$metadata->setSequenceGeneratorDefinition($idElement['sequenceGenerator']);
|
||||
} else if (isset($idElement['customIdGenerator'])) {
|
||||
$customGenerator = $idElement['customIdGenerator'];
|
||||
$metadata->setCustomGeneratorDefinition(array(
|
||||
'class' => (string) $customGenerator['class']
|
||||
));
|
||||
} else if (isset($idElement['tableGenerator'])) {
|
||||
throw MappingException::tableIdGeneratorNotImplemented($className);
|
||||
}
|
||||
@@ -174,19 +284,9 @@ class YamlDriver extends AbstractFileDriver
|
||||
// Evaluate fields
|
||||
if (isset($element['fields'])) {
|
||||
foreach ($element['fields'] as $name => $fieldMapping) {
|
||||
if (!isset($fieldMapping['type'])) {
|
||||
throw MappingException::propertyTypeIsRequired($className, $name);
|
||||
}
|
||||
|
||||
$e = explode('(', $fieldMapping['type']);
|
||||
$fieldMapping['type'] = $e[0];
|
||||
if (isset($e[1])) {
|
||||
$fieldMapping['length'] = substr($e[1], 0, strlen($e[1]) - 1);
|
||||
}
|
||||
$mapping = array(
|
||||
'fieldName' => $name,
|
||||
'type' => $fieldMapping['type']
|
||||
);
|
||||
$mapping = $this->columnToArray($name, $fieldMapping);
|
||||
|
||||
if (isset($fieldMapping['id'])) {
|
||||
$mapping['id'] = true;
|
||||
if (isset($fieldMapping['generator']['strategy'])) {
|
||||
@@ -194,33 +294,6 @@ class YamlDriver extends AbstractFileDriver
|
||||
. strtoupper($fieldMapping['generator']['strategy'])));
|
||||
}
|
||||
}
|
||||
if (isset($fieldMapping['column'])) {
|
||||
$mapping['columnName'] = $fieldMapping['column'];
|
||||
}
|
||||
if (isset($fieldMapping['length'])) {
|
||||
$mapping['length'] = $fieldMapping['length'];
|
||||
}
|
||||
if (isset($fieldMapping['precision'])) {
|
||||
$mapping['precision'] = $fieldMapping['precision'];
|
||||
}
|
||||
if (isset($fieldMapping['scale'])) {
|
||||
$mapping['scale'] = $fieldMapping['scale'];
|
||||
}
|
||||
if (isset($fieldMapping['unique'])) {
|
||||
$mapping['unique'] = (bool)$fieldMapping['unique'];
|
||||
}
|
||||
if (isset($fieldMapping['options'])) {
|
||||
$mapping['options'] = $fieldMapping['options'];
|
||||
}
|
||||
if (isset($fieldMapping['nullable'])) {
|
||||
$mapping['nullable'] = $fieldMapping['nullable'];
|
||||
}
|
||||
if (isset($fieldMapping['version']) && $fieldMapping['version']) {
|
||||
$metadata->setVersionMapping($mapping);
|
||||
}
|
||||
if (isset($fieldMapping['columnDefinition'])) {
|
||||
$mapping['columnDefinition'] = $fieldMapping['columnDefinition'];
|
||||
}
|
||||
|
||||
$metadata->mapField($mapping);
|
||||
}
|
||||
@@ -234,6 +307,10 @@ 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']);
|
||||
}
|
||||
@@ -248,14 +325,14 @@ class YamlDriver extends AbstractFileDriver
|
||||
$joinColumns = array();
|
||||
|
||||
if (isset($oneToOneElement['joinColumn'])) {
|
||||
$joinColumns[] = $this->_getJoinColumnMapping($oneToOneElement['joinColumn']);
|
||||
$joinColumns[] = $this->joinColumnToArray($oneToOneElement['joinColumn']);
|
||||
} else if (isset($oneToOneElement['joinColumns'])) {
|
||||
foreach ($oneToOneElement['joinColumns'] as $name => $joinColumnElement) {
|
||||
if (!isset($joinColumnElement['name'])) {
|
||||
$joinColumnElement['name'] = $name;
|
||||
foreach ($oneToOneElement['joinColumns'] as $joinColumnName => $joinColumnElement) {
|
||||
if ( ! isset($joinColumnElement['name'])) {
|
||||
$joinColumnElement['name'] = $joinColumnName;
|
||||
}
|
||||
|
||||
$joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement);
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,6 +343,10 @@ class YamlDriver extends AbstractFileDriver
|
||||
$mapping['cascade'] = $oneToOneElement['cascade'];
|
||||
}
|
||||
|
||||
if (isset($oneToOneElement['orphanRemoval'])) {
|
||||
$mapping['orphanRemoval'] = (bool)$oneToOneElement['orphanRemoval'];
|
||||
}
|
||||
|
||||
$metadata->mapOneToOne($mapping);
|
||||
}
|
||||
}
|
||||
@@ -287,10 +368,18 @@ class YamlDriver extends AbstractFileDriver
|
||||
$mapping['cascade'] = $oneToManyElement['cascade'];
|
||||
}
|
||||
|
||||
if (isset($oneToManyElement['orphanRemoval'])) {
|
||||
$mapping['orphanRemoval'] = (bool)$oneToManyElement['orphanRemoval'];
|
||||
}
|
||||
|
||||
if (isset($oneToManyElement['orderBy'])) {
|
||||
$mapping['orderBy'] = $oneToManyElement['orderBy'];
|
||||
}
|
||||
|
||||
if (isset($oneToManyElement['indexBy'])) {
|
||||
$mapping['indexBy'] = $oneToManyElement['indexBy'];
|
||||
}
|
||||
|
||||
$metadata->mapOneToMany($mapping);
|
||||
}
|
||||
}
|
||||
@@ -303,6 +392,10 @@ 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']);
|
||||
}
|
||||
@@ -314,14 +407,14 @@ class YamlDriver extends AbstractFileDriver
|
||||
$joinColumns = array();
|
||||
|
||||
if (isset($manyToOneElement['joinColumn'])) {
|
||||
$joinColumns[] = $this->_getJoinColumnMapping($manyToOneElement['joinColumn']);
|
||||
$joinColumns[] = $this->joinColumnToArray($manyToOneElement['joinColumn']);
|
||||
} else if (isset($manyToOneElement['joinColumns'])) {
|
||||
foreach ($manyToOneElement['joinColumns'] as $name => $joinColumnElement) {
|
||||
if (!isset($joinColumnElement['name'])) {
|
||||
$joinColumnElement['name'] = $name;
|
||||
foreach ($manyToOneElement['joinColumns'] as $joinColumnName => $joinColumnElement) {
|
||||
if ( ! isset($joinColumnElement['name'])) {
|
||||
$joinColumnElement['name'] = $joinColumnName;
|
||||
}
|
||||
|
||||
$joinColumns[] = $this->_getJoinColumnMapping($joinColumnElement);
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -350,9 +443,6 @@ class YamlDriver extends AbstractFileDriver
|
||||
if (isset($manyToManyElement['mappedBy'])) {
|
||||
$mapping['mappedBy'] = $manyToManyElement['mappedBy'];
|
||||
} else if (isset($manyToManyElement['joinTable'])) {
|
||||
if (isset($manyToManyElement['inversedBy'])) {
|
||||
$mapping['inversedBy'] = $manyToManyElement['inversedBy'];
|
||||
}
|
||||
|
||||
$joinTableElement = $manyToManyElement['joinTable'];
|
||||
$joinTable = array(
|
||||
@@ -363,25 +453,29 @@ class YamlDriver extends AbstractFileDriver
|
||||
$joinTable['schema'] = $joinTableElement['schema'];
|
||||
}
|
||||
|
||||
foreach ($joinTableElement['joinColumns'] as $name => $joinColumnElement) {
|
||||
if (!isset($joinColumnElement['name'])) {
|
||||
$joinColumnElement['name'] = $name;
|
||||
foreach ($joinTableElement['joinColumns'] as $joinColumnName => $joinColumnElement) {
|
||||
if ( ! isset($joinColumnElement['name'])) {
|
||||
$joinColumnElement['name'] = $joinColumnName;
|
||||
}
|
||||
|
||||
$joinTable['joinColumns'][] = $this->_getJoinColumnMapping($joinColumnElement);
|
||||
$joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
|
||||
foreach ($joinTableElement['inverseJoinColumns'] as $name => $joinColumnElement) {
|
||||
if (!isset($joinColumnElement['name'])) {
|
||||
$joinColumnElement['name'] = $name;
|
||||
foreach ($joinTableElement['inverseJoinColumns'] as $joinColumnName => $joinColumnElement) {
|
||||
if ( ! isset($joinColumnElement['name'])) {
|
||||
$joinColumnElement['name'] = $joinColumnName;
|
||||
}
|
||||
|
||||
$joinTable['inverseJoinColumns'][] = $this->_getJoinColumnMapping($joinColumnElement);
|
||||
$joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
|
||||
$mapping['joinTable'] = $joinTable;
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement['inversedBy'])) {
|
||||
$mapping['inversedBy'] = $manyToManyElement['inversedBy'];
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement['cascade'])) {
|
||||
$mapping['cascade'] = $manyToManyElement['cascade'];
|
||||
}
|
||||
@@ -390,10 +484,80 @@ class YamlDriver extends AbstractFileDriver
|
||||
$mapping['orderBy'] = $manyToManyElement['orderBy'];
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement['indexBy'])) {
|
||||
$mapping['indexBy'] = $manyToManyElement['indexBy'];
|
||||
}
|
||||
|
||||
if (isset($manyToManyElement['orphanRemoval'])) {
|
||||
$mapping['orphanRemoval'] = (bool)$manyToManyElement['orphanRemoval'];
|
||||
}
|
||||
|
||||
$metadata->mapManyToMany($mapping);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate associationOverride
|
||||
if (isset($element['associationOverride']) && is_array($element['associationOverride'])) {
|
||||
|
||||
foreach ($element['associationOverride'] as $fieldName => $associationOverrideElement) {
|
||||
$override = array();
|
||||
|
||||
// Check for joinColumn
|
||||
if (isset($associationOverrideElement['joinColumn'])) {
|
||||
$joinColumns = array();
|
||||
foreach ($associationOverrideElement['joinColumn'] as $name => $joinColumnElement) {
|
||||
if ( ! isset($joinColumnElement['name'])) {
|
||||
$joinColumnElement['name'] = $name;
|
||||
}
|
||||
$joinColumns[] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
$override['joinColumns'] = $joinColumns;
|
||||
}
|
||||
|
||||
// Check for joinTable
|
||||
if (isset($associationOverrideElement['joinTable'])) {
|
||||
|
||||
$joinTableElement = $associationOverrideElement['joinTable'];
|
||||
$joinTable = array(
|
||||
'name' => $joinTableElement['name']
|
||||
);
|
||||
|
||||
if (isset($joinTableElement['schema'])) {
|
||||
$joinTable['schema'] = $joinTableElement['schema'];
|
||||
}
|
||||
|
||||
foreach ($joinTableElement['joinColumns'] as $name => $joinColumnElement) {
|
||||
if ( ! isset($joinColumnElement['name'])) {
|
||||
$joinColumnElement['name'] = $name;
|
||||
}
|
||||
|
||||
$joinTable['joinColumns'][] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
|
||||
foreach ($joinTableElement['inverseJoinColumns'] as $name => $joinColumnElement) {
|
||||
if ( ! isset($joinColumnElement['name'])) {
|
||||
$joinColumnElement['name'] = $name;
|
||||
}
|
||||
|
||||
$joinTable['inverseJoinColumns'][] = $this->joinColumnToArray($joinColumnElement);
|
||||
}
|
||||
|
||||
$override['joinTable'] = $joinTable;
|
||||
}
|
||||
|
||||
$metadata->setAssociationOverride($fieldName, $override);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate associationOverride
|
||||
if (isset($element['attributeOverride']) && is_array($element['attributeOverride'])) {
|
||||
|
||||
foreach ($element['attributeOverride'] as $fieldName => $attributeOverrideElement) {
|
||||
$mapping = $this->columnToArray($fieldName, $attributeOverrideElement);
|
||||
$metadata->setAttributeOverride($fieldName, $mapping);
|
||||
}
|
||||
}
|
||||
|
||||
// Evaluate lifeCycleCallbacks
|
||||
if (isset($element['lifecycleCallbacks'])) {
|
||||
foreach ($element['lifecycleCallbacks'] as $type => $methods) {
|
||||
@@ -408,15 +572,19 @@ class YamlDriver extends AbstractFileDriver
|
||||
* Constructs a joinColumn mapping array based on the information
|
||||
* found in the given join column element.
|
||||
*
|
||||
* @param $joinColumnElement The array join column element
|
||||
* @param array $joinColumnElement The array join column element
|
||||
* @return array The mapping array.
|
||||
*/
|
||||
private function _getJoinColumnMapping($joinColumnElement)
|
||||
private function joinColumnToArray($joinColumnElement)
|
||||
{
|
||||
$joinColumn = array(
|
||||
'name' => $joinColumnElement['name'],
|
||||
'referencedColumnName' => $joinColumnElement['referencedColumnName']
|
||||
);
|
||||
$joinColumn = array();
|
||||
if (isset($joinColumnElement['referencedColumnName'])) {
|
||||
$joinColumn['referencedColumnName'] = (string) $joinColumnElement['referencedColumnName'];
|
||||
}
|
||||
|
||||
if (isset($joinColumnElement['name'])) {
|
||||
$joinColumn['name'] = (string) $joinColumnElement['name'];
|
||||
}
|
||||
|
||||
if (isset($joinColumnElement['fieldName'])) {
|
||||
$joinColumn['fieldName'] = (string) $joinColumnElement['fieldName'];
|
||||
@@ -434,10 +602,6 @@ class YamlDriver extends AbstractFileDriver
|
||||
$joinColumn['onDelete'] = $joinColumnElement['onDelete'];
|
||||
}
|
||||
|
||||
if (isset($joinColumnElement['onUpdate'])) {
|
||||
$joinColumn['onUpdate'] = $joinColumnElement['onUpdate'];
|
||||
}
|
||||
|
||||
if (isset($joinColumnElement['columnDefinition'])) {
|
||||
$joinColumn['columnDefinition'] = $joinColumnElement['columnDefinition'];
|
||||
}
|
||||
@@ -446,10 +610,72 @@ class YamlDriver extends AbstractFileDriver
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
* Parse the given column as array
|
||||
*
|
||||
* @param string $fieldName
|
||||
* @param array $column
|
||||
* @return array
|
||||
*/
|
||||
protected function _loadMappingFile($file)
|
||||
private function columnToArray($fieldName, $column)
|
||||
{
|
||||
return \Symfony\Component\Yaml\Yaml::load($file);
|
||||
$mapping = array(
|
||||
'fieldName' => $fieldName
|
||||
);
|
||||
|
||||
if (isset($column['type'])) {
|
||||
$params = explode('(', $column['type']);
|
||||
$column['type'] = $params[0];
|
||||
$mapping['type'] = $column['type'];
|
||||
|
||||
if (isset($params[1])) {
|
||||
$column['length'] = substr($params[1], 0, strlen($params[1]) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($column['column'])) {
|
||||
$mapping['columnName'] = $column['column'];
|
||||
}
|
||||
|
||||
if (isset($column['length'])) {
|
||||
$mapping['length'] = $column['length'];
|
||||
}
|
||||
|
||||
if (isset($column['precision'])) {
|
||||
$mapping['precision'] = $column['precision'];
|
||||
}
|
||||
|
||||
if (isset($column['scale'])) {
|
||||
$mapping['scale'] = $column['scale'];
|
||||
}
|
||||
|
||||
if (isset($column['unique'])) {
|
||||
$mapping['unique'] = (bool)$column['unique'];
|
||||
}
|
||||
|
||||
if (isset($column['options'])) {
|
||||
$mapping['options'] = $column['options'];
|
||||
}
|
||||
|
||||
if (isset($column['nullable'])) {
|
||||
$mapping['nullable'] = $column['nullable'];
|
||||
}
|
||||
|
||||
if (isset($column['version']) && $column['version']) {
|
||||
$mapping['version'] = $column['version'];
|
||||
}
|
||||
|
||||
if (isset($column['columnDefinition'])) {
|
||||
$mapping['columnDefinition'] = $column['columnDefinition'];
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
protected function loadMappingFile($file)
|
||||
{
|
||||
return Yaml::parse($file);
|
||||
}
|
||||
}
|
||||
|
||||
31
lib/Doctrine/ORM/Mapping/ElementCollection.php
Normal file
31
lib/Doctrine/ORM/Mapping/ElementCollection.php
Normal file
@@ -0,0 +1,31 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("ALL")
|
||||
* @todo check available targets
|
||||
*/
|
||||
final class ElementCollection implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $tableName;
|
||||
}
|
||||
32
lib/Doctrine/ORM/Mapping/Entity.php
Normal file
32
lib/Doctrine/ORM/Mapping/Entity.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
final class Entity implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $repositoryClass;
|
||||
/** @var boolean */
|
||||
public $readOnly = false;
|
||||
}
|
||||
58
lib/Doctrine/ORM/Mapping/EntityResult.php
Normal file
58
lib/Doctrine/ORM/Mapping/EntityResult.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* References an entity in the SELECT clause of a SQL query.
|
||||
* If this annotation is used, the SQL statement should select all of the columns that are mapped to the entity object.
|
||||
* This should include foreign key columns to related entities.
|
||||
* The results obtained when insufficient data is available are undefined.
|
||||
*
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
* @since 2.3
|
||||
*
|
||||
* @Annotation
|
||||
* @Target("ANNOTATION")
|
||||
*/
|
||||
final class EntityResult implements Annotation
|
||||
{
|
||||
|
||||
/**
|
||||
* The class of the result
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $entityClass;
|
||||
|
||||
/**
|
||||
* Maps the columns specified in the SELECT list of the query to the properties or fields of the entity class.
|
||||
*
|
||||
* @var array<\Doctrine\ORM\Mapping\FieldResult>
|
||||
*/
|
||||
public $fields = array();
|
||||
|
||||
/**
|
||||
* Specifies the column name of the column in the SELECT list that is used to determine the type of the entity instance.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $discriminatorColumn;
|
||||
|
||||
}
|
||||
48
lib/Doctrine/ORM/Mapping/FieldResult.php
Normal file
48
lib/Doctrine/ORM/Mapping/FieldResult.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* Is used to map the columns specified in the SELECT list of the query to the properties or fields of the entity class.
|
||||
*
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
* @since 2.3
|
||||
*
|
||||
* @Annotation
|
||||
* @Target("ANNOTATION")
|
||||
*/
|
||||
final class FieldResult implements Annotation
|
||||
{
|
||||
|
||||
/**
|
||||
* Name of the column in the SELECT clause.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* Name of the persistent field or property of the class.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $column;
|
||||
|
||||
}
|
||||
30
lib/Doctrine/ORM/Mapping/GeneratedValue.php
Normal file
30
lib/Doctrine/ORM/Mapping/GeneratedValue.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("PROPERTY")
|
||||
*/
|
||||
final class GeneratedValue implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $strategy = 'AUTO';
|
||||
}
|
||||
28
lib/Doctrine/ORM/Mapping/HasLifecycleCallbacks.php
Normal file
28
lib/Doctrine/ORM/Mapping/HasLifecycleCallbacks.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
final class HasLifecycleCallbacks implements Annotation
|
||||
{
|
||||
}
|
||||
28
lib/Doctrine/ORM/Mapping/Id.php
Normal file
28
lib/Doctrine/ORM/Mapping/Id.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("PROPERTY")
|
||||
*/
|
||||
final class Id implements Annotation
|
||||
{
|
||||
}
|
||||
32
lib/Doctrine/ORM/Mapping/Index.php
Normal file
32
lib/Doctrine/ORM/Mapping/Index.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("ANNOTATION")
|
||||
*/
|
||||
final class Index implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $name;
|
||||
/** @var array<string> */
|
||||
public $columns;
|
||||
}
|
||||
30
lib/Doctrine/ORM/Mapping/InheritanceType.php
Normal file
30
lib/Doctrine/ORM/Mapping/InheritanceType.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
final class InheritanceType implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $value;
|
||||
}
|
||||
42
lib/Doctrine/ORM/Mapping/JoinColumn.php
Normal file
42
lib/Doctrine/ORM/Mapping/JoinColumn.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target({"PROPERTY","ANNOTATION"})
|
||||
*/
|
||||
final class JoinColumn implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $name;
|
||||
/** @var string */
|
||||
public $referencedColumnName = 'id';
|
||||
/** @var boolean */
|
||||
public $unique = false;
|
||||
/** @var boolean */
|
||||
public $nullable = true;
|
||||
/** @var mixed */
|
||||
public $onDelete;
|
||||
/** @var string */
|
||||
public $columnDefinition;
|
||||
/** @var string */
|
||||
public $fieldName; // field name used in non-object hydration (array/scalar)
|
||||
}
|
||||
30
lib/Doctrine/ORM/Mapping/JoinColumns.php
Normal file
30
lib/Doctrine/ORM/Mapping/JoinColumns.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("PROPERTY")
|
||||
*/
|
||||
final class JoinColumns implements Annotation
|
||||
{
|
||||
/** @var array<\Doctrine\ORM\Mapping\JoinColumn> */
|
||||
public $value;
|
||||
}
|
||||
36
lib/Doctrine/ORM/Mapping/JoinTable.php
Normal file
36
lib/Doctrine/ORM/Mapping/JoinTable.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target({"PROPERTY","ANNOTATION"})
|
||||
*/
|
||||
final class JoinTable implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $name;
|
||||
/** @var string */
|
||||
public $schema;
|
||||
/** @var array<\Doctrine\ORM\Mapping\JoinColumn> */
|
||||
public $joinColumns = array();
|
||||
/** @var array<\Doctrine\ORM\Mapping\JoinColumn> */
|
||||
public $inverseJoinColumns = array();
|
||||
}
|
||||
42
lib/Doctrine/ORM/Mapping/ManyToMany.php
Normal file
42
lib/Doctrine/ORM/Mapping/ManyToMany.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("PROPERTY")
|
||||
*/
|
||||
final class ManyToMany implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $targetEntity;
|
||||
/** @var string */
|
||||
public $mappedBy;
|
||||
/** @var string */
|
||||
public $inversedBy;
|
||||
/** @var array<string> */
|
||||
public $cascade;
|
||||
/** @var string */
|
||||
public $fetch = 'LAZY';
|
||||
/** @var boolean */
|
||||
public $orphanRemoval = false;
|
||||
/** @var string */
|
||||
public $indexBy;
|
||||
}
|
||||
36
lib/Doctrine/ORM/Mapping/ManyToOne.php
Normal file
36
lib/Doctrine/ORM/Mapping/ManyToOne.php
Normal file
@@ -0,0 +1,36 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("PROPERTY")
|
||||
*/
|
||||
final class ManyToOne implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $targetEntity;
|
||||
/** @var array<string> */
|
||||
public $cascade;
|
||||
/** @var string */
|
||||
public $fetch = 'LAZY';
|
||||
/** @var string */
|
||||
public $inversedBy;
|
||||
}
|
||||
30
lib/Doctrine/ORM/Mapping/MappedSuperclass.php
Normal file
30
lib/Doctrine/ORM/Mapping/MappedSuperclass.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
final class MappedSuperclass implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $repositoryClass;
|
||||
}
|
||||
@@ -13,7 +13,7 @@
|
||||
* 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
|
||||
* and is licensed under the MIT license. For more information, see
|
||||
* <http://www.phpdoctrine.org>.
|
||||
*/
|
||||
|
||||
@@ -34,8 +34,18 @@ class MappingException extends \Doctrine\ORM\ORMException
|
||||
|
||||
public static function identifierRequired($entityName)
|
||||
{
|
||||
return new self("No identifier/primary key specified for Entity '$entityName'."
|
||||
. " Every Entity must have an identifier/primary key.");
|
||||
if (null !== ($parent = get_parent_class($entityName))) {
|
||||
return new self(sprintf(
|
||||
'No identifier/primary key specified for Entity "%s" sub class of "%s". Every Entity must have an identifier/primary key.',
|
||||
$entityName, $parent
|
||||
));
|
||||
}
|
||||
|
||||
return new self(sprintf(
|
||||
'No identifier/primary key specified for Entity "%s". Every Entity must have an identifier/primary key.',
|
||||
$entityName
|
||||
));
|
||||
|
||||
}
|
||||
|
||||
public static function invalidInheritanceType($entityName, $type)
|
||||
@@ -68,11 +78,73 @@ class MappingException extends \Doctrine\ORM\ORMException
|
||||
return new self("No mapping file found named '$fileName' for class '$entityName'.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception for invalid property name override.
|
||||
*
|
||||
* @param string $className The entity's name
|
||||
* @param string $fieldName
|
||||
*/
|
||||
public static function invalidOverrideFieldName($className, $fieldName)
|
||||
{
|
||||
return new self("Invalid field override named '$fieldName' for class '$className'.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Exception for invalid property type override.
|
||||
*
|
||||
* @param string $className The entity's name
|
||||
* @param string $fieldName
|
||||
*/
|
||||
public static function invalidOverrideFieldType($className, $fieldName)
|
||||
{
|
||||
return new self("The column type of attribute '$fieldName' on class '$className' could not be changed.");
|
||||
}
|
||||
|
||||
public static function mappingNotFound($className, $fieldName)
|
||||
{
|
||||
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 resultMappingNotFound($className, $resultName)
|
||||
{
|
||||
return new self("No result set mapping found named '$resultName' on class '$className'.");
|
||||
}
|
||||
|
||||
public static function emptyQueryMapping($entity, $queryName)
|
||||
{
|
||||
return new self('Query named "'.$queryName.'" in "'.$entity.'" could not be empty.');
|
||||
}
|
||||
|
||||
public static function nameIsMandatoryForQueryMapping($className)
|
||||
{
|
||||
return new self("Query name on entity class '$className' is not defined.");
|
||||
}
|
||||
|
||||
public static function missingQueryMapping($entity, $queryName)
|
||||
{
|
||||
return new self('Query named "'.$queryName.'" in "'.$entity.' requires a result class or result set mapping.');
|
||||
}
|
||||
|
||||
public static function missingResultSetMappingEntity($entity, $resultName)
|
||||
{
|
||||
return new self('Result set mapping named "'.$resultName.'" in "'.$entity.' requires a entity class name.');
|
||||
}
|
||||
|
||||
public static function missingResultSetMappingFieldName($entity, $resultName)
|
||||
{
|
||||
return new self('Result set mapping named "'.$resultName.'" in "'.$entity.' requires a field name.');
|
||||
}
|
||||
|
||||
public static function nameIsMandatoryForSqlResultSetMapping($className)
|
||||
{
|
||||
return new self("Result set mapping name on entity class '$className' is not defined.");
|
||||
}
|
||||
|
||||
public static function oneToManyRequiresMappedBy($fieldName)
|
||||
{
|
||||
return new self("OneToMany mapping on field '$fieldName' requires the 'mappedBy' attribute.");
|
||||
@@ -134,7 +206,17 @@ class MappingException extends \Doctrine\ORM\ORMException
|
||||
|
||||
public static function classIsNotAValidEntityOrMappedSuperClass($className)
|
||||
{
|
||||
return new self('Class '.$className.' is not a valid entity or mapped super class.');
|
||||
if (null !== ($parent = get_parent_class($className))) {
|
||||
return new self(sprintf(
|
||||
'Class "%s" sub class of "%s" is not a valid entity or mapped super class.',
|
||||
$className, $parent
|
||||
));
|
||||
}
|
||||
|
||||
return new self(sprintf(
|
||||
'Class "%s" is not a valid entity or mapped super class.',
|
||||
$className
|
||||
));
|
||||
}
|
||||
|
||||
public static function propertyTypeIsRequired($className, $propertyName)
|
||||
@@ -148,23 +230,36 @@ class MappingException extends \Doctrine\ORM\ORMException
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param string $entity The entity's name
|
||||
* @param string $fieldName The name of the field that was already declared
|
||||
*/
|
||||
public static function duplicateFieldMapping($entity, $fieldName) {
|
||||
public static function duplicateFieldMapping($entity, $fieldName)
|
||||
{
|
||||
return new self('Property "'.$fieldName.'" in "'.$entity.'" was already declared, but it must be declared only once');
|
||||
}
|
||||
|
||||
public static function duplicateAssociationMapping($entity, $fieldName) {
|
||||
public static function duplicateAssociationMapping($entity, $fieldName)
|
||||
{
|
||||
return new self('Property "'.$fieldName.'" in "'.$entity.'" was already declared, but it must be declared only once');
|
||||
}
|
||||
|
||||
public static function singleIdNotAllowedOnCompositePrimaryKey($entity) {
|
||||
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 duplicateResultSetMapping($entity, $resultName)
|
||||
{
|
||||
return new self('Result set mapping named "'.$resultName.'" 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);
|
||||
}
|
||||
|
||||
public static function unsupportedOptimisticLockingType($entity, $fieldName, $unsupportedType) {
|
||||
public static function unsupportedOptimisticLockingType($entity, $fieldName, $unsupportedType)
|
||||
{
|
||||
return new self('Locking type "'.$unsupportedType.'" (specified in "'.$entity.'", field "'.$fieldName.'") '
|
||||
.'is not supported by Doctrine.'
|
||||
);
|
||||
@@ -175,7 +270,7 @@ class MappingException extends \Doctrine\ORM\ORMException
|
||||
if ( ! empty($path)) {
|
||||
$path = '[' . $path . ']';
|
||||
}
|
||||
|
||||
|
||||
return new self(
|
||||
'File mapping drivers must have a valid directory path, ' .
|
||||
'however the given path ' . $path . ' seems to be incorrect!'
|
||||
@@ -190,13 +285,25 @@ class MappingException extends \Doctrine\ORM\ORMException
|
||||
* @param string $owningClass The class that declares the discriminator map.
|
||||
* @return self
|
||||
*/
|
||||
public static function invalidClassInDiscriminatorMap($className, $owningClass) {
|
||||
public static function invalidClassInDiscriminatorMap($className, $owningClass)
|
||||
{
|
||||
return new self(
|
||||
"Entity class '$className' used in the discriminator map of class '$owningClass' ".
|
||||
"does not exist."
|
||||
);
|
||||
}
|
||||
|
||||
public static function duplicateDiscriminatorEntry($className, array $entries, array $map)
|
||||
{
|
||||
return new self(
|
||||
"The entries " . implode(', ', $entries) . " in discriminator map of class '" . $className . "' is duplicated. " .
|
||||
"If the discriminator map is automatically generated you have to convert it to an explicit discriminator map now. " .
|
||||
"The entries of the current map are: @DiscriminatorMap({" . implode(', ', array_map(
|
||||
function($a, $b) { return "'$a': '$b'"; }, array_keys($map), array_values($map)
|
||||
)) . "})"
|
||||
);
|
||||
}
|
||||
|
||||
public static function missingDiscriminatorMap($className)
|
||||
{
|
||||
return new self("Entity class '$className' is using inheritance but no discriminator map was defined.");
|
||||
@@ -212,11 +319,21 @@ class MappingException extends \Doctrine\ORM\ORMException
|
||||
return new self("Discriminator column type on entity class '$className' is not allowed to be '$type'. 'string' or 'integer' type variables are suggested!");
|
||||
}
|
||||
|
||||
public static function nameIsMandatoryForDiscriminatorColumns($className)
|
||||
{
|
||||
return new self("Discriminator column name on entity class '$className' is not defined.");
|
||||
}
|
||||
|
||||
public static function cannotVersionIdField($className, $fieldName)
|
||||
{
|
||||
return new self("Setting Id field '$fieldName' as versionale in entity class '$className' is not supported.");
|
||||
}
|
||||
|
||||
public static function sqlConversionNotAllowedForIdentifiers($className, $fieldName, $type)
|
||||
{
|
||||
return new self("It is not possible to set id field '$fieldName' to type '$type' in entity class '$className'. The type '$type' requires conversion SQL which is not allowed for identifiers.");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @param string $columnName
|
||||
@@ -231,4 +348,94 @@ 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 illegalOrphanRemoval($className, $field)
|
||||
{
|
||||
return new self("Orphan removal is only allowed on one-to-one and one-to-many ".
|
||||
"associations, but " . $className."#" .$field . " is not.");
|
||||
}
|
||||
|
||||
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 discriminator 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."
|
||||
);
|
||||
}
|
||||
|
||||
public static function lifecycleCallbackMethodNotFound($className, $methodName)
|
||||
{
|
||||
return new self("Entity '" . $className . "' has no method '" . $methodName . "' to be registered as lifecycle callback.");
|
||||
}
|
||||
|
||||
public static function invalidFetchMode($className, $annotation)
|
||||
{
|
||||
return new self("Entity '" . $className . "' has a mapping with invalid fetch mode '" . $annotation . "'");
|
||||
}
|
||||
|
||||
public static function compositeKeyAssignedIdGeneratorRequired($className)
|
||||
{
|
||||
return new self("Entity '". $className . "' has a composite identifier but uses an ID generator other than manually assigning (Identity, Sequence). This is not supported.");
|
||||
}
|
||||
|
||||
public static function invalidTargetEntityClass($targetEntity, $sourceEntity, $associationName)
|
||||
{
|
||||
return new self("The target-entity " . $targetEntity . " cannot be found in '" . $sourceEntity."#".$associationName."'.");
|
||||
}
|
||||
|
||||
public static function invalidCascadeOption(array $cascades, $className, $propertyName)
|
||||
{
|
||||
$cascades = implode(", ", array_map(function ($e) { return "'" . $e . "'"; }, $cascades));
|
||||
return new self(sprintf(
|
||||
"You have specified invalid cascade options for %s::$%s: %s; available options: 'remove', 'persist', 'refresh', 'merge', and 'detach'",
|
||||
$className,
|
||||
$propertyName,
|
||||
$cascades
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
40
lib/Doctrine/ORM/Mapping/NamedNativeQueries.php
Normal file
40
lib/Doctrine/ORM/Mapping/NamedNativeQueries.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* Is used to specify an array of native SQL named queries.
|
||||
* The NamedNativeQueries annotation can be applied to an entity or mapped superclass.
|
||||
*
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
* @since 2.3
|
||||
*
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
final class NamedNativeQueries implements Annotation
|
||||
{
|
||||
/**
|
||||
* One or more NamedNativeQuery annotations.
|
||||
*
|
||||
* @var array<\Doctrine\ORM\Mapping\NamedNativeQuery>
|
||||
*/
|
||||
public $value = array();
|
||||
}
|
||||
63
lib/Doctrine/ORM/Mapping/NamedNativeQuery.php
Normal file
63
lib/Doctrine/ORM/Mapping/NamedNativeQuery.php
Normal file
@@ -0,0 +1,63 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* Is used to specify a native SQL named query.
|
||||
* The NamedNativeQuery annotation can be applied to an entity or mapped superclass.
|
||||
*
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
* @since 2.3
|
||||
*
|
||||
* @Annotation
|
||||
* @Target("ANNOTATION")
|
||||
*/
|
||||
final class NamedNativeQuery implements Annotation
|
||||
{
|
||||
|
||||
/**
|
||||
* The name used to refer to the query with the EntityManager methods that create query objects.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
|
||||
/**
|
||||
* The SQL query string.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $query;
|
||||
|
||||
/**
|
||||
* The class of the result.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $resultClass;
|
||||
|
||||
/**
|
||||
* The name of a SqlResultSetMapping, as defined in metadata.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $resultSetMapping;
|
||||
|
||||
}
|
||||
30
lib/Doctrine/ORM/Mapping/NamedQueries.php
Normal file
30
lib/Doctrine/ORM/Mapping/NamedQueries.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("CLASS")
|
||||
*/
|
||||
final class NamedQueries implements Annotation
|
||||
{
|
||||
/** @var array<\Doctrine\ORM\Mapping\NamedQuery> */
|
||||
public $value;
|
||||
}
|
||||
32
lib/Doctrine/ORM/Mapping/NamedQuery.php
Normal file
32
lib/Doctrine/ORM/Mapping/NamedQuery.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("ANNOTATION")
|
||||
*/
|
||||
final class NamedQuery implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $name;
|
||||
/** @var string */
|
||||
public $query;
|
||||
}
|
||||
82
lib/Doctrine/ORM/Mapping/NamingStrategy.php
Normal file
82
lib/Doctrine/ORM/Mapping/NamingStrategy.php
Normal file
@@ -0,0 +1,82 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* A set of rules for determining the physical column and table names
|
||||
*
|
||||
*
|
||||
* @link www.doctrine-project.org
|
||||
* @since 2.3
|
||||
* @author Fabio B. Silva <fabio.bat.silva@gmail.com>
|
||||
*/
|
||||
interface NamingStrategy
|
||||
{
|
||||
/**
|
||||
* Return a table name for an entity class
|
||||
*
|
||||
* @param string $className The fully-qualified class name
|
||||
* @return string A table name
|
||||
*/
|
||||
function classToTableName($className);
|
||||
|
||||
/**
|
||||
* Return a column name for a property
|
||||
*
|
||||
* @param string $propertyName A property
|
||||
* @return string A column name
|
||||
*/
|
||||
function propertyToColumnName($propertyName);
|
||||
|
||||
/**
|
||||
* Return the default reference column name
|
||||
*
|
||||
* @return string A column name
|
||||
*/
|
||||
function referenceColumnName();
|
||||
|
||||
/**
|
||||
* Return a join column name for a property
|
||||
*
|
||||
* @param string $propertyName A property
|
||||
* @return string A join column name
|
||||
*/
|
||||
function joinColumnName($propertyName);
|
||||
|
||||
/**
|
||||
* Return a join table name
|
||||
*
|
||||
* @param string $sourceEntity The source entity
|
||||
* @param string $targetEntity The target entity
|
||||
* @param string $propertyName A property
|
||||
* @return string A join table name
|
||||
*/
|
||||
function joinTableName($sourceEntity, $targetEntity, $propertyName = null);
|
||||
|
||||
/**
|
||||
* Return the foreign key column name for the given parameters
|
||||
*
|
||||
* @param string $entityName A entity
|
||||
* @param string $referencedColumnName A property
|
||||
* @return string A join column name
|
||||
*/
|
||||
function joinKeyColumnName($entityName, $referencedColumnName = null);
|
||||
}
|
||||
40
lib/Doctrine/ORM/Mapping/OneToMany.php
Normal file
40
lib/Doctrine/ORM/Mapping/OneToMany.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("PROPERTY")
|
||||
*/
|
||||
final class OneToMany implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $mappedBy;
|
||||
/** @var string */
|
||||
public $targetEntity;
|
||||
/** @var array<string> */
|
||||
public $cascade;
|
||||
/** @var string */
|
||||
public $fetch = 'LAZY';
|
||||
/** @var boolean */
|
||||
public $orphanRemoval = false;
|
||||
/** @var string */
|
||||
public $indexBy;
|
||||
}
|
||||
40
lib/Doctrine/ORM/Mapping/OneToOne.php
Normal file
40
lib/Doctrine/ORM/Mapping/OneToOne.php
Normal file
@@ -0,0 +1,40 @@
|
||||
<?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 MIT license. For more information, see
|
||||
* <http://www.doctrine-project.org>.
|
||||
*/
|
||||
|
||||
namespace Doctrine\ORM\Mapping;
|
||||
|
||||
/**
|
||||
* @Annotation
|
||||
* @Target("PROPERTY")
|
||||
*/
|
||||
final class OneToOne implements Annotation
|
||||
{
|
||||
/** @var string */
|
||||
public $targetEntity;
|
||||
/** @var string */
|
||||
public $mappedBy;
|
||||
/** @var string */
|
||||
public $inversedBy;
|
||||
/** @var array<string> */
|
||||
public $cascade;
|
||||
/** @var string */
|
||||
public $fetch = 'LAZY';
|
||||
/** @var boolean */
|
||||
public $orphanRemoval = false;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user