Compare commits
1757 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| d5d2b04321 | |||
| ce9c184c83 | |||
| 620de34559 | |||
| b01c71ea5e | |||
| 90e1f7eb29 | |||
| f3ad09ef66 | |||
| dfccb8816c | |||
| 1670ff3fef | |||
| 8870a7ca27 | |||
| ebb7ac9673 | |||
| 5aad8d2001 | |||
| 80713788c9 | |||
| 9f36acbbca | |||
| 044d213a69 | |||
| e5fe525f82 | |||
| 39e4e52908 | |||
| f62014ff34 | |||
| 7935e6a6a3 | |||
| d2acd50352 | |||
| d02337ec22 | |||
| 57f12b6701 | |||
| d500fd21ce | |||
| 30d7b8684e | |||
| d8eb4d4e45 | |||
| 7004c5c0f8 | |||
| 81e55ecdf1 | |||
| 20adc186d4 | |||
| 8c16d9f4b3 | |||
| b3e06a680a | |||
| 3176443e5c | |||
| 83962fa3ba | |||
| 5475f2cd51 | |||
| 30212c0b86 | |||
| 4731463897 | |||
| 87e901f5b1 | |||
| 66f87b6da4 | |||
| 0007242b70 | |||
| 8653e6914b | |||
| 816fec8ef4 | |||
| b0ef09fd35 | |||
| f7a2d6f30e | |||
| 2950ba8fd5 | |||
| 2de5c82a73 | |||
| 758c4e7d5b | |||
| 33f045aec7 | |||
| 35189de442 | |||
| 34e7fc0392 | |||
| a3ce9f52ba | |||
| 6e7da1b0ed | |||
| a6e0b5c1a2 | |||
| 13ab14f965 | |||
| 6729094f63 | |||
| e1aeb17a5a | |||
| b9e20051ef | |||
| 4ab6332176 | |||
| abe2dad521 | |||
| b0f70a13da | |||
| 1e8aca91dd | |||
| b4ac5c4758 | |||
| d161477957 | |||
| a26b99dd1e | |||
| 86e4a92ab0 | |||
| ea425bb82d | |||
| ad0154d319 | |||
| edb70d2b9b | |||
| 9f3355cab4 | |||
| 4107b5bb07 | |||
| 048960c572 | |||
| b826e1f594 | |||
| e5b57cbcdb | |||
| 2870a64792 | |||
| 4d1587bc8d | |||
| 24b69507b2 | |||
| 8b45c90a04 | |||
| 95ae1fe999 | |||
| 9668830ee2 | |||
| f26539c41f | |||
| 3ead688d5f | |||
| 157c233ed6 | |||
| 40b4c2a4c9 | |||
| a7db58d7e4 | |||
| 87e4bfdbec | |||
| ee761817bf | |||
| 4a4b7db651 | |||
| 905427bccc | |||
| 68ee0244a2 | |||
| 7e43775b04 | |||
| dd4e9be06a | |||
| 73b01c288b | |||
| f4f48ebad7 | |||
| ef95f912cb | |||
| 8bbb6adcc7 | |||
| a855765365 | |||
| 3110e69350 | |||
| 4862e7e913 | |||
| 0a52bd502b | |||
| 95492e2863 | |||
| 3cc0a9bef2 | |||
| d743382868 | |||
| 47f1407118 | |||
| 04395f293d | |||
| a44b7a31ef | |||
| 493ef65ce8 | |||
| 3943142b86 | |||
| 786f96363b | |||
| bcf73a8cad | |||
| 2b152504ec | |||
| e554ad3642 | |||
| c801aec334 | |||
| 2c2c16819a | |||
| a48aa9a20f | |||
| 8dadcbed16 | |||
| 86dd776388 | |||
| d83d0871f5 | |||
| fc6baa83a7 | |||
| 35dd2803fc | |||
| e3527752a7 | |||
| 340e0f1686 | |||
| 2ad6153405 | |||
| 0f172ae62d | |||
| f4596bf02c | |||
| ef4f84f696 | |||
| 08d19c9c05 | |||
| e0537f2ee4 | |||
| 0edcf8c83f | |||
| 6ac2c73a8c | |||
| b1a5db0a6b | |||
| 8ec1a81ecd | |||
| b98de03317 | |||
| 251bca3d64 | |||
| b2a79ef0ed | |||
| d9451f5087 | |||
| 84d8dda8eb | |||
| 1d846a4903 | |||
| fe4f985315 | |||
| c5c1d991f2 | |||
| 9ec6573ca4 | |||
| 9800024d59 | |||
| 57b2214433 | |||
| 2f038e5637 | |||
| 0f238f488d | |||
| 59243a6fed | |||
| fbd7f874ac | |||
| 7aee3c8458 | |||
| f3446da34e | |||
| 755594b4bb | |||
| abcf5e9feb | |||
| f243e19b24 | |||
| 5d91b61f83 | |||
| d3ed35e948 | |||
| c5bfe8110a | |||
| 1c18ee94ee | |||
| f72c73766d | |||
| 092139c0b9 | |||
| 43a1fad278 | |||
| dbc4cb15dd | |||
| 758bd650b5 | |||
| ba804c4d9c | |||
| cac794ca20 | |||
| ea09d3e3ba | |||
| f6552c45ae | |||
| 114f5d0279 | |||
| 5638d171d0 | |||
| fa78d360b0 | |||
| ffc35090b9 | |||
| 5156a606e0 | |||
| 2393ef820f | |||
| 9986900b58 | |||
| 07c52ef08f | |||
| 0a6fdda720 | |||
| 841a6b4a19 | |||
| 873da66a90 | |||
| be9f4281e6 | |||
| 57be085166 | |||
| 454c77f37a | |||
| 323a4b8ff0 | |||
| c66e5120e1 | |||
| 1fa7d3a3ba | |||
| a290108ddd | |||
| 446fd740f2 | |||
| a040099b99 | |||
| 78fdc7c1ca | |||
| dfc249b56c | |||
| 577be309cc | |||
| 9798be99e6 | |||
| e3348a11c8 | |||
| 1643a839b3 | |||
| d4a15d26ed | |||
| 485d926dc0 | |||
| 6a5205e9a1 | |||
| 471f7a92bb | |||
| 429ffe561c | |||
| 27cdf5082f | |||
| 4c3751ca4d | |||
| 5f1eaf8239 | |||
| 8b76ef8e41 | |||
| 981a800053 | |||
| 79544f1ad1 | |||
| 93bd3d3f69 | |||
| 975f6f85a2 | |||
| 5a99181eaf | |||
| da5d74f519 | |||
| c878ed0ba4 | |||
| e7e24a1488 | |||
| 3dba884f64 | |||
| 4b30a59f6a | |||
| 704c0808ea | |||
| e738b084b4 | |||
| 77aa761e82 | |||
| 49ac53e751 | |||
| 2c0a431069 | |||
| 61893335ae | |||
| f87ddff585 | |||
| edcd873ff3 | |||
| 3ac7720f5b | |||
| a1fc45c3d7 | |||
| ac01000524 | |||
| 0a313e2b99 | |||
| 18b77760cd | |||
| 65a874c155 | |||
| 1bf851ff6b | |||
| 3309b101b6 | |||
| 27d8caec00 | |||
| 0cb14bd24b | |||
| 133455a041 | |||
| 9c5ba4b3e9 | |||
| 6db849de8d | |||
| 5506b3e725 | |||
| d1ccbbb5e0 | |||
| c8c95d9dc9 | |||
| 7d0ce48cd0 | |||
| c66b76d0be | |||
| febc53147e | |||
| c6279d6214 | |||
| 8deea95fb8 | |||
| 2512044bc5 | |||
| 3a1a124db3 | |||
| d2df0cbc1a | |||
| 15b6ac1b79 | |||
| 8fb60fcd76 | |||
| c8149e3754 | |||
| f49af928b6 | |||
| 63aadcb31f | |||
| 5f1fd4d93c | |||
| 84e8d26371 | |||
| 85fc29e76c | |||
| ad568fa3a7 | |||
| ea8d4d9611 | |||
| d3e74965f9 | |||
| 389c376c43 | |||
| 81eeaa64e4 | |||
| fbad6d9938 | |||
| 825539c792 | |||
| c73fe2d609 | |||
| ac66f768c3 | |||
| 84e2998139 | |||
| 19cab4f333 | |||
| 7d8c50aed8 | |||
| 8d98dc83be | |||
| 3adea33afe | |||
| 55250de396 | |||
| 5fffe53022 | |||
| 7a0ff2fbc5 | |||
| 4f539f4e78 | |||
| 9af827a11e | |||
| 3ddec68d7f | |||
| a5519b927b | |||
| 8add22f589 | |||
| 54f60e8765 | |||
| 6a60b03678 | |||
| 878e3b262b | |||
| a3ad2a6f17 | |||
| 79b32df2d5 | |||
| f40b79bb08 | |||
| ee380aa520 | |||
| dbf91656cb | |||
| 52845dfdb8 | |||
| 78c187e49f | |||
| fe105bd7d2 | |||
| 021e9ea23a | |||
| 794165fa67 | |||
| 6ef0f8b412 | |||
| fcb8630095 | |||
| ceafc139db | |||
| 283c7c2371 | |||
| 0b170cafb2 | |||
| d036f730ca | |||
| 55727bb219 | |||
| dc477978d3 | |||
| 7dda29a892 | |||
| 567cac606a | |||
| 49d435e4a5 | |||
| 5303c05274 | |||
| f6cb258259 | |||
| affb161ddf | |||
| a80f671a22 | |||
| 497cd95731 | |||
| 3ae85beb16 | |||
| 0a76e991b9 | |||
| bfc591b10a | |||
| b274140708 | |||
| a4a9a5618d | |||
| 0cf17a547e | |||
| 35ea526420 | |||
| 8ba04b4ccc | |||
| b83a0c4c96 | |||
| 21d3738125 | |||
| 2bd18b014d | |||
| 39be8f4b3b | |||
| 043b62688b | |||
| 38f5f57c4d | |||
| 2c7a755663 | |||
| 187b4311eb | |||
| 7d2c2cf7ff | |||
| 3771a8fb22 | |||
| 7561bacda5 | |||
| c7d6032010 | |||
| 48d9c5ce79 | |||
| b9d2288ac7 | |||
| 13877c6d58 | |||
| 320a01d822 | |||
| a435df8453 | |||
| a7024843d3 | |||
| 92a35d8e4f | |||
| b8ad6be979 | |||
| 67688043d2 | |||
| 3813ebf44e | |||
| 61728b4a6f | |||
| 56c8befe83 | |||
| 49b38a859c | |||
| c0f404c497 | |||
| 86a239082e | |||
| 2321baaa57 | |||
| b969c86f7c | |||
| 2add330382 | |||
| 383a2d8817 | |||
| dc9e00add2 | |||
| 3169505e07 | |||
| 64f106b631 | |||
| c7b9e5af31 | |||
| b65abedede | |||
| 6ee19ec336 | |||
| c87a9b4732 | |||
| 340c67b4ac | |||
| c084b4b03c | |||
| cb91aca7af | |||
| f0b9d7a37b | |||
| df2d887d97 | |||
| 87f2825cf3 | |||
| 22b99ebc2d | |||
| 9269a1a23e | |||
| b68fc5de60 | |||
| a3f591a556 | |||
| b764cc64aa | |||
| 0da9dac2b8 | |||
| 14a6cb47ab | |||
| fb20f64513 | |||
| 905c25fd10 | |||
| ce92f7dc7b | |||
| ab451a27b3 | |||
| a55f6fc064 | |||
| 7b48d7600e | |||
| a69c22fc24 | |||
| 42d32242b6 | |||
| 031b576e24 | |||
| 49b1649d18 | |||
| 354ab20f08 | |||
| ddbf5c65a3 | |||
| 4961b38a8a | |||
| 4b861eaa56 | |||
| 2886627dc2 | |||
| d1c60633a9 | |||
| 80be5cd036 | |||
| 4cd297bf87 | |||
| 13fc554930 | |||
| 0d624f8a1f | |||
| 90b22a14e0 | |||
| fdd5608367 | |||
| 86eeceda74 | |||
| 8a45ffac0e | |||
| 3d92d3b07f | |||
| f4b9d57358 | |||
| 1a1b2967f4 | |||
| e2f3be3ead | |||
| fc6c1ae499 | |||
| e0f548a021 | |||
| 4be5809230 | |||
| a9d106a1cf | |||
| 6605aae410 | |||
| 7cf1d24b43 | |||
| 5a71c664f6 | |||
| a98807c378 | |||
| a2f0430b94 | |||
| b4d0c95a80 | |||
| 2d968c3623 | |||
| 365cbb0148 | |||
| 9402b4e4a1 | |||
| a5a017fcd3 | |||
| b28e7b7f0d | |||
| 653bc21c6a | |||
| 8ccb05276c | |||
| dacf0d2b11 | |||
| e3ac65cb0e | |||
| 74fda80847 | |||
| 0893aa8f04 | |||
| f76749fa48 | |||
| 6c3ead0a16 | |||
| 83daee274b | |||
| d73ea377d1 | |||
| 95b4a3e80b | |||
| ea5b473638 | |||
| 47be3285c5 | |||
| db56419dbc | |||
| cab39ce4a1 | |||
| b32ae6ff0c | |||
| 3f03bb0e8b | |||
| 170cd1455f | |||
| 666e529b6e | |||
| d0505e3c96 | |||
| 42abe70f99 | |||
| be4cb23bb9 | |||
| e1c3c72bc9 | |||
| 6eb00a2c29 | |||
| 4c84cba83a | |||
| 1ab94221e7 | |||
| e024031214 | |||
| e29659c930 | |||
| 6a954eae08 | |||
| feafa476b1 | |||
| 7a49773881 | |||
| 1660a94941 | |||
| 3db192ce0b | |||
| a5477daf45 | |||
| 4944fc8ebd | |||
| 6c396454da | |||
| 2cd1739658 | |||
| b9ad4ef289 | |||
| e1963fafcd | |||
| 089117ca85 | |||
| 509f7eb89c | |||
| 1481025d48 | |||
| 4a5e21cc49 | |||
| 36747901ab | |||
| 640d12269d | |||
| fece59aa14 | |||
| 431e72421c | |||
| f2a6975754 | |||
| 1f6dd0fd45 | |||
| 788cb631e0 | |||
| 5ec3916ff1 | |||
| 2a3338a41e | |||
| e65ca9c03d | |||
| dcd2c9a7b4 | |||
| 4f47a209c2 | |||
| 544e36b75c | |||
| b2e70d20cc | |||
| 021d535d6c | |||
| b8b3221d51 | |||
| 477de51126 | |||
| 4ecb6187fa | |||
| c800679ed2 | |||
| 94d37ad056 | |||
| 5677cbe254 | |||
| 9b240f7b45 | |||
| ad6f85734b | |||
| d2342d53da | |||
| f724d14b31 | |||
| fce833ddde | |||
| bfd9f07780 | |||
| 5f2fab79e2 | |||
| e5efe8eb84 | |||
| b153ea4aaa | |||
| 49f2d624ba | |||
| bc16f47f4f | |||
| e11779c1f9 | |||
| ed44026f12 | |||
| 0f988a4c3b | |||
| e9bbff5f20 | |||
| a0c5e3a82d | |||
| 7626d413ec | |||
| dbbdb94bb1 | |||
| 13c4e7eca4 | |||
| b8fe0413ed | |||
| 152600f985 | |||
| 47a1b8d191 | |||
| d7dd082f8e | |||
| d55efb4f00 | |||
| 7dbadf32e9 | |||
| ab6ee6e95e | |||
| 8a0858fbd7 | |||
| dbc30827f8 | |||
| 0aafbb03e2 | |||
| 323f37b744 | |||
| ac63427a51 | |||
| 3d9bea7fb6 | |||
| b9a1178fbe | |||
| 318fe08eb5 | |||
| 42edba6bc6 | |||
| 3b2654013b | |||
| ea6e1310f2 | |||
| 6ea90dd62f | |||
| 51719203ed | |||
| e97d79fe03 | |||
| 62811200d8 | |||
| ea201f3b86 | |||
| 9e50cad232 | |||
| e3bf41c7c5 | |||
| 07e919a2d5 | |||
| a171b3d081 | |||
| 0e2b578b6b | |||
| 3e10de58ed | |||
| 1825a677b8 | |||
| 907942b01a | |||
| 0c4af841dd | |||
| 1bd3936db0 | |||
| 1ba07aeb5f | |||
| cfbed0396e | |||
| b9e0493980 | |||
| 404b367cc2 | |||
| 4830ada35d | |||
| e6cf4ec493 | |||
| 3f3556070d | |||
| 265825ae84 | |||
| e19aa6843e | |||
| 259507567a | |||
| 3039df31c2 | |||
| ca554c4f5f | |||
| 621179c7d6 | |||
| 1ae7eb3d78 | |||
| 270283dff0 | |||
| da71345f1e | |||
| 3a596f34f8 | |||
| 557bda6115 | |||
| 13272ace8c | |||
| cac822603b | |||
| 6dd2be22a2 | |||
| 8734941ba6 | |||
| 37aa5519ac | |||
| d4d9f4e634 | |||
| ff58d0faef | |||
| d77f5b16c3 | |||
| 8b943076a1 | |||
| a6b95adc9b | |||
| f880ebc4e4 | |||
| 4fee7253de | |||
| e0a30eea69 | |||
| c2dccc68b9 | |||
| d8685786c6 | |||
| 8f3b856bd6 | |||
| a6f056b8c8 | |||
| c5afc4647e | |||
| 9249ad3039 | |||
| badfcf5c06 | |||
| 454b99a360 | |||
| 12ecfecf3e | |||
| 9e790feeae | |||
| b059bb2d1a | |||
| 1e2770a94a | |||
| 7beef23040 | |||
| 3389d234d5 | |||
| 2f465109fb | |||
| f6f985d833 | |||
| b7f69bed7e | |||
| 640999e627 | |||
| a5f506b463 | |||
| 37a341dd1b | |||
| 5f4af41551 | |||
| 0b172ed567 | |||
| c2243b780c | |||
| 6ffebb0950 | |||
| e71d8e94d7 | |||
| 1956cc64ae | |||
| 13fadb5ffc | |||
| 77a3819272 | |||
| bdad67cf6c | |||
| 002b3a59ec | |||
| 1f34eb6675 | |||
| d0e9f834d4 | |||
| 1aabda2074 | |||
| fc41341e3b | |||
| 41a6158fd0 | |||
| 8c5b6f674c | |||
| e0b72c4f74 | |||
| 7e7239be87 | |||
| 9bdb01799b | |||
| 7d31929283 | |||
| ad6aa3e7b5 | |||
| b94efaa63a | |||
| 8c5d10dc3e | |||
| 364e937aa4 | |||
| f738099c66 | |||
| f5aeab0daf | |||
| 532f517109 | |||
| bb077b5467 | |||
| dd71782fcd | |||
| b91199671a | |||
| 989158bc3d | |||
| cde1704866 | |||
| 5b33d09da0 | |||
| f3827a1a83 | |||
| d682b72735 | |||
| 1fc596fd1e | |||
| 90b75a008c | |||
| c3d95eed7d | |||
| 87dd1bafa7 | |||
| 74ac9cff0c | |||
| af83bfda42 | |||
| 5c1ceb7e97 | |||
| af88f79f02 | |||
| 4feecd49f4 | |||
| c7ac95c807 | |||
| e1223f38cd | |||
| 7954345cc4 | |||
| 4d670018f2 | |||
| 6bbd25d132 | |||
| 15fc47b4eb | |||
| 93d38814f3 | |||
| 40db648d81 | |||
| ab7c5090f1 | |||
| 5dd75fba7f | |||
| c22994f545 | |||
| d65e395b22 | |||
| b497164f39 | |||
| 4753aee9c3 | |||
| 8fcdfc5fe3 | |||
| 3cb94db156 | |||
| bf531d4022 | |||
| 16ad6757d4 | |||
| efbf2075f4 | |||
| 8e928c9c24 | |||
| 79e5907765 | |||
| abb9508c36 | |||
| 1db221c771 | |||
| f217a14f23 | |||
| dca5d3e6ec | |||
| c02da89654 | |||
| ce07230cc6 | |||
| bb34789f8f | |||
| 8c0050c036 | |||
| 073402ff9a | |||
| 23d17a609e | |||
| 7bd1a47843 | |||
| 024e5b746c | |||
| 337315f004 | |||
| 3de92094b3 | |||
| 61f242e006 | |||
| dbeb44f19a | |||
| 8bd3148d70 | |||
| 51d0921483 | |||
| 2cf472082f | |||
| a61e663cf0 | |||
| 9915452311 | |||
| e53b060022 | |||
| 6c133983fb | |||
| 9a5aebcfd2 | |||
| 9ca2d6634d | |||
| 8ddd368c65 | |||
| edf5fdb7fc | |||
| 46822da6d7 | |||
| 3a0f2f2882 | |||
| 9b566d0bf7 | |||
| 7e2431cb6d | |||
| d5b65f0d89 | |||
| aacda0bef9 | |||
| d23b0379cc | |||
| 42756c6586 | |||
| b7d9f3187c | |||
| 6836a8672e | |||
| 3499d65104 | |||
| f00b6fa588 | |||
| b7719e3b41 | |||
| b71ccf7a58 | |||
| c07cfca3ae | |||
| eafca6a25f | |||
| 7ce537a76f | |||
| 217597e3d5 | |||
| 15ffef7d1a | |||
| 7d9f29d626 | |||
| 6bbc1e7d58 | |||
| e412f0681f | |||
| 968814bd57 | |||
| 57531e1899 | |||
| 181250be29 | |||
| 56ea84d109 | |||
| e0bbe3491a | |||
| a34ece03fe | |||
| 916ca4b4db | |||
| 86b432961e | |||
| 3b2c0a2654 | |||
| 0c631c5ea8 | |||
| 72578e46b5 | |||
| 8844131a0b | |||
| 25f36fc3da | |||
| 175b315526 | |||
| ccf84cd3d1 | |||
| b149e6147a | |||
| 86880f8b1f | |||
| 0cdb8c5b20 | |||
| 05a058bdd7 | |||
| 25c2c9660a | |||
| 517cbee900 | |||
| 9581386e84 | |||
| 7732be0faf | |||
| 3e6d11f76f | |||
| 74222ea346 | |||
| 26e5ad4b07 | |||
| bf7ba23ba9 | |||
| f6e8d102ec | |||
| c8d915b5e8 | |||
| 21c7f383bb | |||
| 42f057bc8a | |||
| c4e60ede3d | |||
| 93c0fc88d5 | |||
| de140e50e1 | |||
| a8e34443b4 | |||
| 76c425cf22 | |||
| 730b840409 | |||
| fff8e37e4e | |||
| ae9ca671d1 | |||
| b985985a99 | |||
| e56c823c0f | |||
| 613d559fe2 | |||
| 731b89a756 | |||
| 8900ba4566 | |||
| 6dc183a357 | |||
| 51bd623a85 | |||
| 27cd78653d | |||
| 4275decc05 | |||
| ada8a9ed67 | |||
| c1552a4c88 | |||
| b1f9ac335d | |||
| 12369a5cbd | |||
| 2e7c63e012 | |||
| 95185d3a93 | |||
| aa95de08ae | |||
| 9556e5d2bb | |||
| e5dc0b7836 | |||
| 728f95492f | |||
| 3eeca0315a | |||
| bca71c3a16 | |||
| 0d910ea6a5 | |||
| 27b628827f | |||
| 8c7fe30509 | |||
| 93068ab224 | |||
| 3088530d9d | |||
| 4fac0621e7 | |||
| ca24835df8 | |||
| 53e0163388 | |||
| 23a86b901d | |||
| 7ae222268e | |||
| 6386b2c8a9 | |||
| fa0f77d26e | |||
| 33dab9dd5e | |||
| 95340d6d37 | |||
| 5bd3d98250 | |||
| 05adb043f2 | |||
| 9ecbb09b45 | |||
| 5c68659e64 | |||
| 896f4e08f6 | |||
| 0116fb2e51 | |||
| cec0404b1f | |||
| 0b7485e9da | |||
| 6481d69a25 | |||
| 00a8645ec7 | |||
| 8bb0fe1e68 | |||
| 92110de1a8 | |||
| 3c181b4d60 | |||
| 765dccee26 | |||
| 532a3cf0e8 | |||
| 247fc51a69 | |||
| 91bb128a15 | |||
| 11a2167a2c | |||
| ba059c379d | |||
| 9497909749 | |||
| 8735203573 | |||
| f19f0c0e81 | |||
| 7d26617092 | |||
| 8f919ffa1b | |||
| 78bfeb6e29 | |||
| abd043ee15 | |||
| 991095ae50 | |||
| de24a92118 | |||
| 52b4db46d3 | |||
| 6e7ed8e7a2 | |||
| 1aeb698c76 | |||
| bc7c5ad13b | |||
| 7ae96a0521 | |||
| 9add6a51e7 | |||
| a8315038b9 | |||
| 059898848a | |||
| 260cf02457 | |||
| 8a2193d986 | |||
| c5b370dabc | |||
| 648e698d9e | |||
| dfd7ead466 | |||
| cdb3b5b0ad | |||
| 7556cb259a | |||
| ef1d542814 | |||
| 428987406c | |||
| 4e2bb41358 | |||
| d605b4b218 | |||
| 9d5f4782b0 | |||
| 675d62b47a | |||
| 4568378314 | |||
| 60d50d8ba5 | |||
| ba6ed131db | |||
| e8f6c583e0 | |||
| 218b4a3137 | |||
| 1fb9ef08bb | |||
| be34d78454 | |||
| e691cc0bc2 | |||
| b60e38dd92 | |||
| 9d394fa0ff | |||
| a0bf0d3e66 | |||
| 742867e2f9 | |||
| 6be3eb6499 | |||
| 748d88bb87 | |||
| fb2e7943c7 | |||
| aa18b438d4 | |||
| 99c9e4b2d9 | |||
| 4d1eb83019 | |||
| faa4890fb3 | |||
| b0120a2ed2 | |||
| 680480b9dc | |||
| a0e5eb03d2 | |||
| 4015bf30e6 | |||
| 70539e9f51 | |||
| defcaec071 | |||
| 767545935a | |||
| 4967f84ef3 | |||
| 5727c4edf8 | |||
| 3d4c4bcd54 | |||
| 15185405fb | |||
| 92d3c32172 | |||
| d37141b035 | |||
| 216363d8a7 | |||
| 574ad26ced | |||
| 25803e3814 | |||
| ddf2caaccc | |||
| f63d66fbda | |||
| c843b47425 | |||
| d8b4ed58c7 | |||
| d8035412c0 | |||
| 895a83b094 | |||
| 6b58f95127 | |||
| dc09566ea3 | |||
| edaf29f5c3 | |||
| 0456469c60 | |||
| eee07bbc46 | |||
| c06f25fcf5 | |||
| 1cb1b0b9cb | |||
| 35ea34eb4a | |||
| 91436fdb58 | |||
| ea46eeb09b | |||
| ad2beb841c | |||
| ff99cdbf61 | |||
| 5b2e91b1ed | |||
| 6893452022 | |||
| 751bc7cc4a | |||
| 8c088c3384 | |||
| 2108ec7613 | |||
| 3fcd90f551 | |||
| 133ca2c273 | |||
| 9da50baed0 | |||
| e3f02b51bc | |||
| 300ebfec7d | |||
| 8a5d079a8a | |||
| 8d53c9e0f7 | |||
| de45170f2c | |||
| d5193add08 | |||
| 992bc2cc16 | |||
| 107d452fcf | |||
| 2dbcff013d | |||
| 961d350e04 | |||
| fc2f13b519 | |||
| 240996c13c | |||
| 8da9cf58a4 | |||
| b67f2a304f | |||
| 3d2912af01 | |||
| 55d3368eab | |||
| 7954d31728 | |||
| 5e32d9a020 | |||
| e1c27e492b | |||
| 316a44f59c | |||
| 5e1a3f7148 | |||
| 567d440dcd | |||
| c898292ebe | |||
| 30e639fe69 | |||
| fc634c94ed | |||
| a4823d5d41 | |||
| b79b55d8b0 | |||
| dd79069cc5 | |||
| 30dae81e7e | |||
| e4a583f8dc | |||
| 8be7975d54 | |||
| f052cf1fbf | |||
| c4144f2913 | |||
| a29ed02053 | |||
| 55d564066e | |||
| 4d537ad9fd | |||
| 1b09df691f | |||
| 151ac4ac0e | |||
| 79c8f1f799 | |||
| cbf299955f | |||
| dbae08e7af | |||
| 24bf2405a3 | |||
| daef261403 | |||
| 2f76d86069 | |||
| 0792dc8006 | |||
| 98b7048db7 | |||
| 5f199ccb19 | |||
| 0fcf75f468 | |||
| 70b38affd1 | |||
| 6bb25e0ffd | |||
| 0444627e09 | |||
| bdaae065bb | |||
| 45379c7bf9 | |||
| 4a540e87f1 | |||
| 374c41002b | |||
| 8bf0941f2b | |||
| 835300e3c6 | |||
| bd1f60623e | |||
| 84703373a2 | |||
| bcfc1dbb28 | |||
| 55630e22a3 | |||
| bee11f3d82 | |||
| 441ce5fd45 | |||
| c995bb7e51 | |||
| 86863ec30e | |||
| 83cf04b31b | |||
| 848e55cc93 | |||
| 51014591b3 | |||
| 449236ee12 | |||
| fa94b803e1 | |||
| 3336f3a184 | |||
| c590cb1c92 | |||
| 4d2fc8af52 | |||
| 57d8e44fef | |||
| 1ef28546b9 | |||
| 24c93edf2b | |||
| 575f4b8520 | |||
| 2db271dab3 | |||
| 16d8d44437 | |||
| 386e855939 | |||
| 7c6af25309 | |||
| 945b1b315c | |||
| 6bdc50a29e | |||
| 489d34cbfa | |||
| 18c6b9cf8d | |||
| ebb23807cf | |||
| 0744a4fac8 | |||
| 81227b9371 | |||
| 0e0376ce67 | |||
| c1c0d862b9 | |||
| 59b994f0d8 | |||
| b63436d325 | |||
| 62f709868e | |||
| 24e4cdc555 | |||
| 280d2341df | |||
| e979c5ad5e | |||
| 95719adc40 | |||
| c3900b0259 | |||
| 0dbf4ebc08 | |||
| 145f6e0bb6 | |||
| 01ed2f1f48 | |||
| 5a0e147c2b | |||
| 53b68579af | |||
| 1b9647da65 | |||
| 2b4929fa97 | |||
| 11568decb4 | |||
| 63fd1e8e13 | |||
| ccba377f13 | |||
| fedef53f93 | |||
| 619cf164a6 | |||
| 1bea0ae66e | |||
| 633d1fce44 | |||
| 99b4aee754 | |||
| fb453f674d | |||
| 6fa51c2fe3 | |||
| 75714dab64 | |||
| 5792ac3e22 | |||
| c2a46396ff | |||
| f371589935 | |||
| 8d6364f1ac | |||
| d263484e91 | |||
| 1ded86021a | |||
| 32d4d0f820 | |||
| d2731aa8b9 | |||
| 7a2f8e0e00 | |||
| af398ca8b6 | |||
| 79ae112c5b | |||
| 6d4e21d006 | |||
| be67fdf155 | |||
| 02357b0650 | |||
| ea8d9b22cd | |||
| 6e01b437e2 | |||
| 1c4020810f | |||
| 99e2f36794 | |||
| f375eec0a0 | |||
| effee75d57 | |||
| d5c31fab74 | |||
| 5bac261b33 | |||
| 0dc5586348 | |||
| c8da2da9e7 | |||
| 801b19154c | |||
| e77a66700d | |||
| cfd8f6fa94 | |||
| 51860d34c7 | |||
| fe442681b7 | |||
| 3e256e5093 | |||
| 14b83e418d | |||
| 5ba5c930a0 | |||
| a943a6ca25 | |||
| 97c5d94a64 | |||
| 1e4e9f7e49 | |||
| 4ab955d399 | |||
| 1cb36c8707 | |||
| aab596d14d | |||
| 6d92ca5b56 | |||
| b441c07ef5 | |||
| 151c1ccdd6 | |||
| 1f85ff1d65 | |||
| 5b1e28c323 | |||
| 539ba488e9 | |||
| 36856814b0 | |||
| b808417359 | |||
| 7cbf6e3bdf | |||
| 1a89c6c8be | |||
| cb9e7e8775 | |||
| 51b0212527 | |||
| 863ef72c00 | |||
| 01f6491421 | |||
| 93aa4bd23f | |||
| 2219c81975 | |||
| d30c36264e | |||
| 36f0e45e7e | |||
| fe67cad896 | |||
| ee46ba2474 | |||
| 4ca59d62c4 | |||
| 491099d963 | |||
| b795c1ae4a | |||
| ae9700da16 | |||
| 531d7c8a78 | |||
| c54e600d6f | |||
| 7d54e103f9 | |||
| 1ca45f8215 | |||
| c06506d487 | |||
| 2360eeba61 | |||
| 0e000f3427 | |||
| cf0cae7c87 | |||
| 759307050a | |||
| 68bbc90920 | |||
| 22c11fca68 | |||
| 695c24b79f | |||
| c95cc8d799 | |||
| fda57cd6cc | |||
| 62145acb8c | |||
| 3198d66753 | |||
| 2432b98be5 | |||
| 15851ba97c | |||
| de4e63d7f9 | |||
| 1e8dbecbf5 | |||
| 1f45c2c218 | |||
| 4e534051b7 | |||
| 11ab2f1e2f | |||
| 62b2d038dc | |||
| d67b32795a | |||
| 7b79b98571 | |||
| 76fa5b89c9 | |||
| 782d4a6a77 | |||
| 223f67065a | |||
| b94e3f6629 | |||
| 968d500f11 | |||
| 1eef6a7303 | |||
| bb3fd6988e | |||
| 37fc82d7e1 | |||
| b9ab9a869d | |||
| 45f2aa7406 | |||
| f226c9ba3b | |||
| c2109e1760 | |||
| 07312d25fe | |||
| 2ad860180e | |||
| c9d2edd7d5 | |||
| 0d6176e4e2 | |||
| 6ea406251c | |||
| cb1e59cdcf | |||
| d814603118 | |||
| 799d6bb815 | |||
| 14cb8a45d3 | |||
| 3bd3a39642 | |||
| a4056c8341 | |||
| e794517876 | |||
| 22819d5ee2 | |||
| 3dd722d46f | |||
| b4a0b60c71 | |||
| 598c2bd2ad | |||
| 399fcee0af | |||
| 9a6c7b835b | |||
| 39af292171 | |||
| 3ce7315250 | |||
| c4ba48c59a | |||
| f68d62ddb7 | |||
| dcc1389878 | |||
| cdfcec981c | |||
| 7f42f0bef5 | |||
| 13f7b93659 | |||
| bf8849aff8 | |||
| 54de278a83 | |||
| 9371d47587 | |||
| ffc9c15324 | |||
| b55d8fedce | |||
| 505f7985ab | |||
| bd17e8a713 | |||
| d6f0abf28d | |||
| 83ae20e295 | |||
| 669f248797 | |||
| 23f8a55fff | |||
| eace30919c | |||
| fbd8ecadac | |||
| 806bf80764 | |||
| 3cea2e392e | |||
| 682246df28 | |||
| 63d8eaa4a5 | |||
| cc83805fd6 | |||
| 69a623f2a4 | |||
| 15cbf0c236 | |||
| 9557989011 | |||
| 2e0a56dd27 | |||
| 224ae55b18 | |||
| abdc68627f | |||
| 41f1447a0b | |||
| 218738906e | |||
| b5e79cd126 | |||
| c03a93ee98 | |||
| 81132af603 | |||
| 98c45b8ca4 | |||
| 0d185b77f3 | |||
| dbf4a018ef | |||
| a83ab33799 | |||
| b55b20f37b | |||
| 0377550b6f | |||
| 415abed013 | |||
| df9e8eb0c5 | |||
| 1f913041b7 | |||
| f3f023268a | |||
| e2092648bc | |||
| 2b96155ec7 | |||
| a29e54630b | |||
| 6851a2f432 | |||
| cfa31ff677 | |||
| 370d758768 | |||
| 23cf0e56a7 | |||
| eaccb88e46 | |||
| 27297e29fd | |||
| b486686474 | |||
| b7ab941d98 | |||
| 9121e9272b | |||
| dd9966016b | |||
| 203a594bb1 | |||
| ee31554bb4 | |||
| 3366556ffe | |||
| 7d9b45446d | |||
| a616d27c72 | |||
| 606250ec74 | |||
| 37680e63f5 | |||
| b42be92f19 | |||
| 64c818d6e8 | |||
| 94a9184bf0 | |||
| 8c74ed4d00 | |||
| b471ea3f5e | |||
| 99ddfe268e | |||
| 26fc318af5 | |||
| c2ebe4c670 | |||
| 587433f112 | |||
| 2d2866d9ed | |||
| efd2122038 | |||
| 73c6cc5637 | |||
| f27628c8f6 | |||
| cc47889993 | |||
| c1bc93fb4c | |||
| 1ac6c00a79 | |||
| 68b7b1c020 | |||
| fc253b52bf | |||
| 776a251123 | |||
| 41fa50246e | |||
| 0d03334891 | |||
| 86d6f5a346 | |||
| 1dcace00ef | |||
| 857d5c0e13 | |||
| f4acafe8de | |||
| e11d8304b7 | |||
| abe586ff0a | |||
| 192e496ba5 | |||
| 4a130e6eed | |||
| d8cec79b3e | |||
| 7e84d06c57 | |||
| 3f4325175f | |||
| 75841054e1 | |||
| e2a2341fd7 | |||
| b13d1d44bd | |||
| 4ee97bc737 | |||
| 993815f327 | |||
| 9df12dfe3c | |||
| 92164057aa | |||
| 733d4fbc88 | |||
| a443364928 | |||
| d900b28a70 | |||
| bdfdc38331 | |||
| 0fabbe3988 | |||
| 3e05205618 | |||
| 2a70e61742 | |||
| 6de5fa2019 | |||
| 7f9ae9556b | |||
| f7ec2b6b98 | |||
| 4d6cb53bf2 | |||
| 6c33df603e | |||
| 9bb0181bd2 | |||
| c329d87fb5 | |||
| 6ed54f3d8c | |||
| 1d585313bc | |||
| 73c148e1a1 | |||
| c373e75ce5 | |||
| 8c09041896 | |||
| c95753523f | |||
| 9ee9008019 | |||
| efe5a71124 | |||
| c1e8393705 | |||
| 1ad8449a69 | |||
| ba7156770e | |||
| e6da017bc1 | |||
| ad34011d1b | |||
| 395be286f8 | |||
| f0eb29fbd5 | |||
| 6d4b352c30 | |||
| 859e2c7717 | |||
| d8e7b88811 | |||
| c75ac94d68 | |||
| c4d1669d50 | |||
| 2402ead3e7 | |||
| def8aa7cdc | |||
| 73a452fdf1 | |||
| b2e3f7442a | |||
| e3f1eeda55 | |||
| 6f9d48f779 | |||
| 64df33b1f2 | |||
| 7647c55283 | |||
| 35cf073f0b | |||
| 4b16d82bb9 | |||
| dca2948371 | |||
| ab2aed3387 | |||
| 18ad158655 | |||
| e03f8427ed | |||
| 300a016dd2 | |||
| c17a1cfcc6 | |||
| 6b9ef31df8 | |||
| a9e172b975 | |||
| 277e3cc13e | |||
| ad5d636937 | |||
| e71fc2e809 | |||
| cbab515ad7 | |||
| ba00de55cf | |||
| 5f57b77a53 | |||
| 6e968a6fbd | |||
| 93f4941821 | |||
| 0ccad9bbff | |||
| 517fb75637 | |||
| 110f02dbf8 | |||
| 4753a99824 | |||
| 10e4c6ce95 | |||
| 15716e903f | |||
| d1ef94d81a | |||
| b69d54c827 | |||
| 747b83aa4e | |||
| 7062f625d3 | |||
| a9510ee353 | |||
| fa34e2eec0 | |||
| 8035e95184 | |||
| deae5457aa | |||
| b0a585ac3e | |||
| ae246a42d1 | |||
| d2c1d130c9 | |||
| 40a7d8f123 | |||
| 1fc24197af | |||
| 3375db806e | |||
| dae8e52d07 | |||
| 9162b02766 | |||
| 78d1d4f279 | |||
| 1985bf4e38 | |||
| a79997e6cc | |||
| 2e8f58615e | |||
| 8b638abf13 | |||
| 1d68177cb9 | |||
| 23154fc83e | |||
| 6a8107a879 | |||
| b7ae11104e | |||
| 2449b15fc8 | |||
| 3fd86129c2 | |||
| 6b7e307948 | |||
| d43bc87268 | |||
| 3516a8bae0 | |||
| 6c21c597cc | |||
| a7695a2dbd | |||
| 819e96abf3 | |||
| 6ccd53562b | |||
| 52f97eaf4c | |||
| f591fda712 | |||
| b71bdb6ca8 | |||
| a04b4447b2 | |||
| 49ffb1386e | |||
| 2bbf422bb2 | |||
| 3ccc313fe5 | |||
| c011c39bbc | |||
| 1a5759448e | |||
| 113684c7db | |||
| bfacb6333e | |||
| 4756e44cdb | |||
| e353fbc41e | |||
| 98ada1938e | |||
| 1b0df626c4 | |||
| 0367ac2c6c | |||
| 2507c49e67 | |||
| 7f14a5ed4d | |||
| 4fe0728551 | |||
| 8d95f88112 | |||
| 1bd06a4350 | |||
| 4a861f18e8 | |||
| d5591b8d42 | |||
| c361c03ae5 | |||
| 11686389da | |||
| a32e8b6024 | |||
| b2bfe5781e | |||
| 9589a394eb | |||
| 9f9d19415d | |||
| 3c0e687a6d | |||
| 5366629e26 | |||
| c2a974a58e | |||
| e227fd0729 | |||
| 55213b7624 | |||
| 6850b3af2e | |||
| fe2bf5a1d9 | |||
| 07e3f3f1e3 | |||
| f112b19d8f | |||
| 3ed3abeda2 | |||
| 31e741aa43 | |||
| 864c62c345 | |||
| e479529347 | |||
| 24b0f8d944 | |||
| 0ec677106e | |||
| f77ce9878b | |||
| d688ca175b | |||
| fa09277f1f | |||
| 9922f0ad60 | |||
| b58ac08dd0 | |||
| f5b53a653b | |||
| bb20446250 | |||
| d82cd47c01 | |||
| 29403b63b1 | |||
| 97c972b545 | |||
| ae5fd2b587 | |||
| 4f19878dd6 | |||
| 71af7bcfbd | |||
| 2e97b91c13 | |||
| 9e65b23120 | |||
| 54cff0fb5d | |||
| 72b5975bc8 | |||
| d5732c83b5 | |||
| 76e3308edd | |||
| e3f81d83b1 | |||
| da977a547a | |||
| 0d8b51507d | |||
| 8106600dd7 | |||
| 3f3027f09c | |||
| 99e27e964b | |||
| 14dc411096 | |||
| 724f3504d0 | |||
| fa4b1197c6 | |||
| f5204f01e6 | |||
| a2d8691d8c | |||
| 00a967d9fc | |||
| 46fdbace15 | |||
| dcf5ac2a38 | |||
| 6f4664623b | |||
| 633c20fdcd | |||
| b62bdceaf3 | |||
| e787bb2351 | |||
| 432169fdea | |||
| 7e3ca6da9c | |||
| 157795fad4 | |||
| 5b28c52a10 | |||
| 324db2fa3f | |||
| f2cfae0583 | |||
| c143995fbd | |||
| fed06d7728 | |||
| e07d8ca163 | |||
| a16f1004be | |||
| 645fae72ae | |||
| 2ebb787b74 | |||
| 5fc88d3076 | |||
| ec6d706aeb | |||
| 75bdfedc77 | |||
| a1ee256cf5 | |||
| c1c4f6c928 | |||
| 34b4c42873 | |||
| e5d97e5a29 | |||
| ffd685d8b4 | |||
| 72b8da4c7f | |||
| 3f9b8d8e8c | |||
| 03137da76e | |||
| 4b7f8bd9bc | |||
| d0f2460e0c | |||
| 39cfe4dc79 | |||
| 271ef211a9 | |||
| 537cb2dcf3 | |||
| cb056899e6 | |||
| a32d321f27 | |||
| 89ef862606 | |||
| 710a388123 | |||
| 7a28085378 | |||
| 3354756933 | |||
| 489ba0917f | |||
| 1dfd429211 | |||
| 9a43c1990f | |||
| 20bae71fd7 | |||
| 7a6104c735 | |||
| a85382f92a | |||
| 5059a87784 | |||
| 501c259580 | |||
| 1f20e88cdd | |||
| 804011a5ea | |||
| 929ffc2113 | |||
| 9cd7241196 | |||
| 82b54a9069 | |||
| 1de1f50b1f | |||
| 3c3bfb7f0b | |||
| 261c91f33d | |||
| e3b9b6f81b | |||
| 61308c5b41 | |||
| ee46d1e941 | |||
| 0d415dac54 | |||
| 0eec5cb298 | |||
| d9d68c9491 | |||
| 1b98b0aa8c | |||
| c4ca8f1e4b | |||
| 9697c7783a | |||
| 6f09f68dbb | |||
| d245ac394c | |||
| f032388d38 | |||
| 3a1f15d9f0 | |||
| e0ebeb8974 | |||
| 5ead904ccc | |||
| 74d9766be2 | |||
| 6bbd153c6a | |||
| 8a4c5dab54 | |||
| a5240de569 | |||
| 7fd9d62581 | |||
| 4a52c2b590 | |||
| 8a84804416 | |||
| ce1952d796 | |||
| 5b473b2d5a | |||
| 12f8c0d723 | |||
| b4d39f465f | |||
| 290286e1a9 | |||
| b1081dd079 | |||
| d23b9384b0 | |||
| 7c4dd74609 | |||
| f1a7928192 | |||
| 3fb79847ce | |||
| 9ad35eb88a | |||
| a095c94e21 | |||
| fd7415b7f1 | |||
| 2150dcab44 | |||
| 8907e1cb69 | |||
| 0de470d446 | |||
| 6182a6922a | |||
| ab27ae6a6d | |||
| e148c425fa | |||
| 9ffb1e5057 | |||
| f9cf3640ff | |||
| 68db46e4cc | |||
| be3ce48e92 | |||
| b71b45c5c8 | |||
| 822f7a7f36 | |||
| 149cdd7d96 | |||
| 08a5361321 | |||
| 3d190ae839 | |||
| c33a5af377 | |||
| 3ecc305238 | |||
| 0eea1d7963 | |||
| c2aa3ae44a | |||
| e91dd1aa12 | |||
| ea4e6e9651 | |||
| ff1f891ec3 | |||
| 5269fd2679 | |||
| 355b1bce2b | |||
| 803532a14e | |||
| 7fdd2f4e9f | |||
| f1a3b7a8ca | |||
| 91f9be1443 | |||
| 761fa4653b | |||
| a1e1021b3b | |||
| 3d314cc76f | |||
| 57e5bd000a | |||
| 7700c16b56 | |||
| a0f1d7d933 | |||
| eb08fbaa0b | |||
| b13ab488cc | |||
| 677f771b3b | |||
| 2bd3dd6bb6 | |||
| ec8fa8381b | |||
| b7cc3f9158 | |||
| aaada7e5ab | |||
| 312c17bbe2 | |||
| e5f1ed5f56 | |||
| 0ff1a4fcc4 | |||
| 849a326d4b | |||
| 27a03777c3 | |||
| 377ff2ed5b | |||
| 6994c109d2 | |||
| a6731f4a03 | |||
| 17ea843ddf | |||
| bab9f9d6f7 | |||
| bc5eeeac25 | |||
| 8c59fc3856 | |||
| 88501d3b35 | |||
| 5ae926a415 | |||
| 3f0e116fb2 | |||
| d2580b69ec | |||
| e6d51ce85c | |||
| 3c15820e78 | |||
| 59498620a0 | |||
| e1547e58f8 | |||
| a4160b78f2 | |||
| 0510c1af41 | |||
| 2beaa726cd | |||
| d7f068fdbf | |||
| 6143eb68a8 | |||
| be4128e359 | |||
| bd37881db7 | |||
| 74532d2509 | |||
| 6bb24e5b42 | |||
| d0cecaddb6 | |||
| 50e1abbc65 | |||
| d556fb11c4 | |||
| 1991550f49 | |||
| 7d967d2762 | |||
| 65aaebef0b | |||
| 4b15596d37 | |||
| 887209cfaa | |||
| a36f876792 | |||
| ef423dc1b8 | |||
| f0b44d28a9 | |||
| c251fa7bec | |||
| 8ee27b9b14 | |||
| dcb588e02d | |||
| b0362ea68f | |||
| 9e36ea7983 | |||
| d9a279ba2b | |||
| c22eba6217 | |||
| 4183ded30c | |||
| 903f70fc8f | |||
| 2e0b436e73 | |||
| a347b88c7c | |||
| fae8c48fa7 | |||
| 1a0cc394f3 | |||
| fdbca3d7ad | |||
| c147816549 | |||
| ce70af484d | |||
| 4e3b41331d | |||
| 22fa0d292c | |||
| 5bc3f7c648 | |||
| 55e3e94b52 | |||
| b89554b6c6 | |||
| 170de0b822 | |||
| 7e701fa7cb | |||
| 159aa4adf3 | |||
| 6e64f102b9 | |||
| 95c9e878a5 | |||
| 60382f2b97 | |||
| cf5557694e | |||
| 826b3b2102 | |||
| abdaeb3e08 | |||
| 6c78b4ee3b | |||
| c91a4534f0 | |||
| c9b16cd4db | |||
| 4a80ba1351 | |||
| 47bf22324b | |||
| 7b1c9b2816 | |||
| c812f9c110 | |||
| d56c2bba9e | |||
| b8f8d9162c | |||
| 2e4e79cef2 | |||
| 5fa407d697 | |||
| 633cd1b140 | |||
| 6d49bffcfe | |||
| 82350f3c81 | |||
| f1e2fc3b42 | |||
| dd4f460e57 | |||
| 81a316377b | |||
| 4a3b74950e | |||
| 0b846865c9 | |||
| cfa2d8f8fb | |||
| f9a85d69f4 | |||
| 80ecf1c3da | |||
| 7106b114f1 | |||
| cb04fccbd2 | |||
| b7d0b0c3d6 | |||
| e57e600945 | |||
| b12ebb9c7e | |||
| d1877d78a7 | |||
| 93519c3c57 | |||
| 4fbbfb37e4 | |||
| 41b8969b02 | |||
| 793eddad32 | |||
| 7ab08af442 | |||
| 5bf0607460 | |||
| 102bc35016 | |||
| 7b085c67c6 | |||
| a3caaafd69 | |||
| 9b92aa46e6 | |||
| c8b7476b5d | |||
| 65af1f2933 | |||
| 7265ef854a | |||
| 0b05eb1a27 | |||
| decb85b493 | |||
| 2edeacdd16 | |||
| 4102c309de | |||
| 6331e1fd5a | |||
| 7293c70dca | |||
| de937ace09 | |||
| 7dd1322ea4 | |||
| 52fdb0e89c | |||
| 68c8850922 | |||
| 718ad85313 | |||
| 1e6333a18e | |||
| b99551e326 | |||
| ad43351306 | |||
| 503a188dd7 | |||
| 3f61f5423e | |||
| 43794de52b | |||
| cbb3deda1f | |||
| fd2e76944e | |||
| a81338cbe3 | |||
| b57ada8703 | |||
| ee0111ad0c | |||
| 0c20f975de | |||
| 8c221e9e0e | |||
| 8093c6ab3b | |||
| db3e6aadc7 | |||
| 452f2e8766 | |||
| 271dd20c16 | |||
| cb70c7f885 | |||
| 8d83dedd2b | |||
| 270a7ca961 | |||
| 98cf8ff17d | |||
| fd51902c31 | |||
| f809bba0f4 | |||
| a0d576ed91 | |||
| cf052cb46b | |||
| d7302ceba5 | |||
| 088745109f | |||
| 37b9731c24 | |||
| 2520407b44 | |||
| 2b865ef222 | |||
| 2214c634b4 | |||
| 226094f844 | |||
| 8f6079b040 | |||
| 3b05c856ef | |||
| 4fb0b9b0e9 | |||
| 2d2be272ff | |||
| 67060012cc | |||
| f87c437d60 | |||
| 4164104918 | |||
| 808e91a38b | |||
| c38c406cde | |||
| 939ceba776 | |||
| 1897254498 | |||
| e864df5129 | |||
| 7c88c486d8 | |||
| 02c6dd37d7 | |||
| ea48a33b33 | |||
| 9a1a55471b | |||
| 7cb402d2bc | |||
| 43d0596c12 | |||
| 46bcbb4f4b | |||
| d5cc4c2d64 | |||
| b0f2b1077e | |||
| b369e5c492 | |||
| 5aa94c1a25 | |||
| 6f4ed54579 | |||
| a5b2445ec2 | |||
| 51c3637ed2 | |||
| 878b167d95 | |||
| 5690f5a5bc | |||
| 68e331a960 | |||
| 3009c3fcf0 | |||
| 250b5b0928 | |||
| 661fc54ba2 | |||
| 52bc8eef02 | |||
| 71503fbdcc | |||
| 6b3be1b0f9 | |||
| e42c2b442f | |||
| ce1f7f34e5 | |||
| 522fb3201a | |||
| 69e41f4597 | |||
| 49f358fa93 | |||
| 16b300b139 | |||
| 98a39dff91 | |||
| 6a4d1ec3da | |||
| 4736478ddf | |||
| 25c00ea088 | |||
| e8c2bec566 | |||
| a7dfb571eb | |||
| 857ec53870 | |||
| f2083f1eaf | |||
| 99f7ebd712 | |||
| 20fbbeb666 | |||
| efb231a765 | |||
| bfb71139a5 | |||
| b30abb50d5 | |||
| bd1a34985b | |||
| 338d244560 | |||
| c48c8b622f | |||
| 1d1196207a | |||
| 6b6801bfcd | |||
| 3a50245ddf | |||
| 0fcffb5da5 | |||
| c222176bc1 | |||
| 22b9593de9 | |||
| 6ac65948db | |||
| d2d93054c8 | |||
| f09624f769 | |||
| 6df5cb10ef | |||
| 98850e5157 | |||
| f1baed32b6 | |||
| a142c1e951 | |||
| b688ec789e | |||
| 9fae1ed0e1 | |||
| b35b3862fd | |||
| 27c7878647 | |||
| f8abead728 | |||
| ca50c16f88 | |||
| 6d0b6f887d | |||
| cda768b721 | |||
| 12d547c1a2 | |||
| 27dc21e24e | |||
| 712e6b8f2a | |||
| ec37380175 | |||
| 73cb94f657 | |||
| b3ea8978b1 | |||
| 008a0914eb | |||
| 01f8e16b38 | |||
| c095b69f67 | |||
| 4c8c5ac239 | |||
| cfc847133e | |||
| 30b430f1cf | |||
| 516c7612a5 | |||
| 3bb3d5a1d7 |
@@ -16,6 +16,9 @@ themes/classic/views/
|
||||
out
|
||||
gen
|
||||
|
||||
db/
|
||||
async-queue/
|
||||
|
||||
composer.lock
|
||||
|
||||
*.log
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace PHPSTORM_META {
|
||||
|
||||
// Reflect
|
||||
use Kiri\Di\Container;
|
||||
use Psr\Container\ContainerInterface;
|
||||
|
||||
override(ContainerInterface::get(0), map('@'));
|
||||
override(Container::get(0), map('@'));
|
||||
override(Container::make(0), map('@'));
|
||||
override(Container::create(0), map('@'));
|
||||
// override(\Hyperf\Utils\Context::get(0), map('@'));
|
||||
// override(\make(0), map('@'));
|
||||
override(\di(0), map('@'));
|
||||
override(\duplicate(0), map('@'));
|
||||
|
||||
}
|
||||
@@ -1,206 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation;
|
||||
|
||||
|
||||
use DirectoryIterator;
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Component;
|
||||
|
||||
/**
|
||||
* Class Annotation
|
||||
* @package Annotation
|
||||
*/
|
||||
class Annotation extends Component
|
||||
{
|
||||
|
||||
|
||||
private Loader $_loader;
|
||||
|
||||
|
||||
private array $_model_sets = [];
|
||||
private array $_model_gets = [];
|
||||
private array $_model_relate = [];
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $setName
|
||||
* @param string $method
|
||||
*/
|
||||
public function addSets(string $class, string $setName, string $method)
|
||||
{
|
||||
$this->_model_sets[$class][$setName] = $method;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $setName
|
||||
* @param string $method
|
||||
*/
|
||||
public function addGets(string $class, string $setName, string $method)
|
||||
{
|
||||
$this->_model_gets[$class][$setName] = $method;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $setName
|
||||
* @param string $method
|
||||
*/
|
||||
public function addRelate(string $class, string $setName, string $method)
|
||||
{
|
||||
$this->_model_relate[$class][$setName] = $method;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $class
|
||||
* @return array
|
||||
*/
|
||||
public function getGets($class): array
|
||||
{
|
||||
return $this->_model_gets[$class] ?? [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $class
|
||||
* @return array
|
||||
*/
|
||||
public function getSets($class): array
|
||||
{
|
||||
return $this->_model_gets[$class] ?? [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string|null $setName
|
||||
* @return array|string|null
|
||||
*/
|
||||
public function getGetMethodName(string $class, string $setName = null): array|null|string
|
||||
{
|
||||
$gets = $this->_model_gets[$class] ?? null;
|
||||
if ($gets == null) {
|
||||
return null;
|
||||
}
|
||||
if (empty($setName)) return $gets;
|
||||
return $gets[$setName] ?? null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string|null $method
|
||||
* @return array|string|null
|
||||
*/
|
||||
public function getRelateMethods(string $class, string $method = null): array|null|string
|
||||
{
|
||||
$gets = $this->_model_relate[$class] ?? null;
|
||||
if ($gets == null) {
|
||||
return null;
|
||||
}
|
||||
if (empty($method)) return $gets;
|
||||
return $gets[$method] ?? null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $setName
|
||||
* @return mixed|null
|
||||
*/
|
||||
public function getSetMethodName(string $class, string $setName): ?string
|
||||
{
|
||||
if (!isset($this->_model_sets[$class])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$lists = $this->_model_sets[$class];
|
||||
|
||||
if (isset($lists[$setName])) {
|
||||
return $lists[$setName];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public function init(): void
|
||||
{
|
||||
$this->_loader = new Loader();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Loader
|
||||
*/
|
||||
public function getLoader(): Loader
|
||||
{
|
||||
return $this->_loader;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Loader $loader
|
||||
* @return Loader
|
||||
*/
|
||||
public function setLoader(Loader $loader): Loader
|
||||
{
|
||||
return $this->_loader = $loader;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $className
|
||||
* @param string $method
|
||||
* @return array 根据类名获取注解
|
||||
* 根据类名获取注解
|
||||
*/
|
||||
public function getMethods(string $className, string $method = ''): mixed
|
||||
{
|
||||
return $this->_loader->getMethod($className, $method);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
*/
|
||||
public function injectProperty(object $class)
|
||||
{
|
||||
$this->_loader->injectProperty($class::class, $class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param string $namespace
|
||||
* @param string $alias
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function read(string $path, string $namespace = 'App', string $alias = 'root'): void
|
||||
{
|
||||
|
||||
$this->_loader->_scanDir(new DirectoryIterator($path), $namespace);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $dir
|
||||
* @param string|array $outPath
|
||||
* @throws Exception
|
||||
*/
|
||||
public function runtime(string $dir, string|array $outPath = '')
|
||||
{
|
||||
if (empty($outPath)) {
|
||||
$outPath = [];
|
||||
} else if (is_string($outPath)) {
|
||||
$outPath = [$outPath];
|
||||
}
|
||||
$this->_loader->loadByDirectory($dir, $outPath);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Aop;
|
||||
use Snowflake\IAspect;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
defined('ASPECT_ERROR') or define('ASPECT_ERROR', 'Aspect annotation must implement ');
|
||||
|
||||
/**
|
||||
* Class Aspect
|
||||
* @package Annotation
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)] class Aspect extends Attribute
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Aspect constructor.
|
||||
* @param string $aspect
|
||||
*/
|
||||
public function __construct(public string $aspect)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public function execute(mixed $class, mixed $method = ''): mixed
|
||||
{
|
||||
// TODO: Change the autogenerated stub
|
||||
if (!in_array(IAspect::class, class_implements($this->aspect))) {
|
||||
throw new Exception(ASPECT_ERROR . IAspect::class);
|
||||
}
|
||||
/** @var Aop $aop */
|
||||
$aop = Snowflake::app()->get('aop');
|
||||
|
||||
$aop->aop_add([$class, $method], $this->aspect);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation;
|
||||
|
||||
|
||||
use Exception;
|
||||
use HttpServer\IInterface\Task;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
|
||||
/**
|
||||
* Class Asynchronous
|
||||
* @package Annotation
|
||||
* Task任务
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_CLASS)] class Asynchronous extends Attribute
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Asynchronous constructor.
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct(public string $name)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): mixed
|
||||
{
|
||||
$async = Snowflake::app()->getAsync();
|
||||
$async->addAsync($this->name, $class);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation;
|
||||
|
||||
|
||||
use Annotation\Route\After;
|
||||
use Annotation\Route\Interceptor;
|
||||
use Annotation\Route\Limits;
|
||||
use Annotation\Route\Middleware as RMiddleware;
|
||||
use HttpServer\Route\Node;
|
||||
use ReflectionException;
|
||||
use Snowflake\Exception\ComponentException;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Attribute
|
||||
* @package Annotation
|
||||
*/
|
||||
abstract class Attribute implements IAnnotation
|
||||
{
|
||||
|
||||
|
||||
|
||||
public function execute(mixed $class, mixed $method = ''): mixed
|
||||
{
|
||||
// TODO: Implement execute() method.
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Exception\ComponentException;
|
||||
use Snowflake\Snowflake;
|
||||
use Snowflake\Event as SEvent;
|
||||
|
||||
|
||||
/**
|
||||
* Class Event
|
||||
* @package Annotation
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)] class Event extends Attribute
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Event constructor.
|
||||
* @param string $name
|
||||
* @param array $params
|
||||
*/
|
||||
public function __construct(public string $name, public array $params = [])
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): mixed
|
||||
{
|
||||
// TODO: Implement execute() method.
|
||||
SEvent::on($this->name, [$class, $method], $this->params);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation;
|
||||
|
||||
|
||||
use Exception;
|
||||
use ReflectionProperty;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Inject
|
||||
* @package Annotation
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_PROPERTY)] class Inject extends Attribute
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Inject constructor.
|
||||
* @param string $className
|
||||
* @param array $args
|
||||
*/
|
||||
public function __construct(private string $className, private array $args = [])
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): mixed
|
||||
{
|
||||
$injectValue = $this->parseInjectValue();
|
||||
if (!($method instanceof ReflectionProperty)) {
|
||||
$method = new ReflectionProperty($class, $method);
|
||||
}
|
||||
|
||||
/** @var ReflectionProperty $class */
|
||||
if ($method->isPrivate() || $method->isProtected()) {
|
||||
$method = 'set' . ucfirst($class->getName());
|
||||
if (!method_exists($class, $method)) {
|
||||
return false;
|
||||
}
|
||||
$class->$method($injectValue);
|
||||
} else {
|
||||
$class->{$method->getName()} = $injectValue;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
private function parseInjectValue(): mixed
|
||||
{
|
||||
if (class_exists($this->className)) {
|
||||
$injectValue = Snowflake::createObject($this->className, $this->args);
|
||||
} else if (Snowflake::app()->has($this->className)) {
|
||||
$injectValue = Snowflake::app()->get($this->className);
|
||||
} else {
|
||||
$injectValue = $this->className;
|
||||
}
|
||||
// if (!empty($this->args) && is_object($injectValue)) {
|
||||
// Snowflake::configure($injectValue, $this->args);
|
||||
// }
|
||||
return $injectValue;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation;
|
||||
|
||||
|
||||
use Kafka\ConsumerInterface;
|
||||
use Kafka\TaskContainer;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Kafka
|
||||
* @package Annotation
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_CLASS)] class Kafka extends Attribute
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Kafka constructor.
|
||||
* @param string $topic
|
||||
*/
|
||||
public function __construct(public string $topic)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return mixed
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): mixed
|
||||
{
|
||||
if (!($class instanceof ConsumerInterface)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @var TaskContainer $container */
|
||||
$container = Snowflake::app()->get('kafka-container');
|
||||
$container->addConsumer($this->topic, [$class, 'onHandler']);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,354 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation;
|
||||
|
||||
|
||||
use Annotation\Model\Get;
|
||||
use Annotation\Model\Relation;
|
||||
use Annotation\Model\Set;
|
||||
use Attribute;
|
||||
use DirectoryIterator;
|
||||
use Exception;
|
||||
use ReflectionMethod;
|
||||
use Snowflake\Abstracts\BaseObject;
|
||||
use Snowflake\Snowflake;
|
||||
use Throwable;
|
||||
|
||||
|
||||
/**
|
||||
* Class Loader
|
||||
* @package Annotation
|
||||
*/
|
||||
class Loader extends BaseObject
|
||||
{
|
||||
|
||||
|
||||
private array $_classes = [];
|
||||
|
||||
|
||||
private array $_directory = [];
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getDirectory(): array
|
||||
{
|
||||
return $this->_directory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param $namespace
|
||||
* @throws Exception
|
||||
*/
|
||||
public function loader($path, $namespace)
|
||||
{
|
||||
$this->_scanDir(new DirectoryIterator($path), $namespace);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getClasses(): array
|
||||
{
|
||||
return $this->_classes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $property
|
||||
* @return mixed
|
||||
*/
|
||||
public function getProperty(string $class, string $property = ''): mixed
|
||||
{
|
||||
if (!isset($this->_classes[$class])) {
|
||||
return null;
|
||||
}
|
||||
$properties = $this->_classes[$class]['property'];
|
||||
if (!empty($property) && isset($properties[$property])) {
|
||||
return $properties[$property];
|
||||
}
|
||||
return $properties;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param mixed $handler
|
||||
* @return Loader
|
||||
*/
|
||||
public function injectProperty(string $class, object $handler): static
|
||||
{
|
||||
$properties = $this->getProperty($class);
|
||||
if (empty($properties)) {
|
||||
return $this;
|
||||
}
|
||||
foreach ($properties as $property => $attributes) {
|
||||
foreach ($attributes as $attribute) {
|
||||
$attribute->execute($handler, $property);
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @param string $method
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMethod(string $class, string $method = ''): array
|
||||
{
|
||||
if (!isset($this->_classes[$class])) {
|
||||
return [];
|
||||
}
|
||||
$properties = $this->_classes[$class]['methods'];
|
||||
if (!empty($method) && isset($properties[$method])) {
|
||||
return $properties[$method];
|
||||
}
|
||||
return $properties;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $class
|
||||
* @return array
|
||||
*/
|
||||
public function getTarget(string $class): array
|
||||
{
|
||||
return $this->_classes[$class] ?? [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param DirectoryIterator $paths
|
||||
* @param $namespace
|
||||
* @throws Exception
|
||||
*/
|
||||
public function _scanDir(DirectoryIterator $paths, $namespace)
|
||||
{
|
||||
foreach ($paths as $path) {
|
||||
if ($path->isDot() || str_starts_with($path->getFilename(), '.')) {
|
||||
continue;
|
||||
}
|
||||
if ($path->isDir()) {
|
||||
$iterator = new DirectoryIterator($path->getRealPath());
|
||||
$directory = rtrim($path->getRealPath(), '/');
|
||||
if (!isset($this->_directory[$directory])) {
|
||||
$this->_directory[$directory] = [];
|
||||
}
|
||||
$this->_scanDir($iterator, $namespace);
|
||||
} else {
|
||||
$this->readFile($path, $namespace);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param DirectoryIterator $path
|
||||
* @param $namespace
|
||||
* @throws Exception
|
||||
*/
|
||||
private function readFile(DirectoryIterator $path, $namespace)
|
||||
{
|
||||
try {
|
||||
if ($path->getExtension() !== 'php') {
|
||||
return;
|
||||
}
|
||||
$replace = $this->getReflect($path, $namespace);
|
||||
if (empty($replace) || count($replace->getAttributes(Target::class)) < 1) {
|
||||
return;
|
||||
}
|
||||
$this->appendFileToDirectory($path->getRealPath(), $replace->getName());
|
||||
|
||||
$_array['handler'] = $replace->newInstance();
|
||||
$_array['target'] = [];
|
||||
$_array['methods'] = [];
|
||||
$_array['property'] = [];
|
||||
|
||||
$_array = $this->_targets($replace, $_array);
|
||||
$_array = $this->_methods($replace, $_array);
|
||||
$_array = $this->_properties($replace, $_array);
|
||||
|
||||
$this->_classes[$replace->getName()] = $_array;
|
||||
} catch (Throwable $throwable) {
|
||||
$this->addError($throwable, 'throwable');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param string $namespace
|
||||
* @return \ReflectionClass|null
|
||||
* @throws \ReflectionException
|
||||
* @throws \Snowflake\Exception\NotFindClassException
|
||||
*/
|
||||
private function getReflect(DirectoryIterator $path, string $namespace): ?\ReflectionClass
|
||||
{
|
||||
return Snowflake::getDi()->getReflect($this->explodeFileName($path, $namespace));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \ReflectionClass $replace
|
||||
* @param array $_array
|
||||
* @return array
|
||||
*/
|
||||
private function _targets(\ReflectionClass $replace, array $_array): array
|
||||
{
|
||||
foreach ($replace->getAttributes() as $attribute) {
|
||||
if ($attribute->getName() == Attribute::class) {
|
||||
continue;
|
||||
}
|
||||
if ($attribute->getName() == Target::class) {
|
||||
continue;
|
||||
}
|
||||
$_array['target'][] = $attribute->newInstance();
|
||||
}
|
||||
return $_array;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \ReflectionClass $replace
|
||||
* @param array $_array
|
||||
* @return array
|
||||
*/
|
||||
private function _methods(\ReflectionClass $replace, array $_array): array
|
||||
{
|
||||
$methods = $replace->getMethods(ReflectionMethod::IS_PUBLIC);
|
||||
foreach ($methods as $method) {
|
||||
$_method = [];
|
||||
foreach ($method->getAttributes() as $attribute) {
|
||||
if (!class_exists($attribute->getName())) {
|
||||
continue;
|
||||
}
|
||||
$_method[] = $attribute->newInstance();
|
||||
}
|
||||
$_array['methods'][$method->getName()] = $_method;
|
||||
}
|
||||
return $_array;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param \ReflectionClass $replace
|
||||
* @param array $_array
|
||||
* @return array
|
||||
*/
|
||||
private function _properties(\ReflectionClass $replace, array $_array): array
|
||||
{
|
||||
$methods = $replace->getProperties();
|
||||
foreach ($methods as $method) {
|
||||
$_property = [];
|
||||
if ($method->isStatic()) continue;
|
||||
foreach ($method->getAttributes() as $attribute) {
|
||||
if (!class_exists($attribute->getName())) {
|
||||
continue;
|
||||
}
|
||||
$_property[] = $attribute->newInstance();
|
||||
}
|
||||
$_array['property'][$method->getName()] = $_property;
|
||||
}
|
||||
return $_array;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param string|array $outPath
|
||||
* @throws Exception
|
||||
*/
|
||||
public function loadByDirectory(string $path, string|array $outPath = '')
|
||||
{
|
||||
try {
|
||||
$path = '/' . trim($path, '/');
|
||||
foreach ($this->_directory as $key => $_path) {
|
||||
$key = '/' . trim($key, '/');
|
||||
if (!str_starts_with($key, $path) || in_array($key, $outPath)) {
|
||||
continue;
|
||||
}
|
||||
$this->execute($_path);
|
||||
}
|
||||
} catch (Throwable $exception) {
|
||||
$this->addError($exception, 'throwable');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param DirectoryIterator $path
|
||||
* @param string $namespace
|
||||
* @return string
|
||||
*/
|
||||
private function explodeFileName(DirectoryIterator $path, string $namespace): string
|
||||
{
|
||||
$replace = str_replace(APP_PATH . 'app', '', $path->getRealPath());
|
||||
|
||||
$replace = str_replace('.php', '', $replace);
|
||||
$replace = str_replace(DIRECTORY_SEPARATOR, '\\', $replace);
|
||||
$explode = explode('\\', $replace);
|
||||
array_shift($explode);
|
||||
|
||||
return $namespace . '\\' . implode('\\', $explode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $filePath
|
||||
* @param string $className
|
||||
*/
|
||||
public function appendFileToDirectory(string $filePath, string $className)
|
||||
{
|
||||
$array = explode('/', $filePath);
|
||||
unset($array[count($array) - 1]);
|
||||
|
||||
$array = '/' . trim(implode('/', $array), '/');
|
||||
|
||||
$this->_directory[$array][] = $className;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $classes
|
||||
*/
|
||||
private function execute(array $classes)
|
||||
{
|
||||
if (empty($classes)) {
|
||||
return;
|
||||
}
|
||||
$annotation = Snowflake::getAnnotation();
|
||||
|
||||
foreach ($classes as $className) {
|
||||
$annotations = $this->_classes[$className] ?? null;
|
||||
if ($annotations === null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/** @var \Annotation\Attribute $value */
|
||||
foreach ($annotations['target'] ?? [] as $value) {
|
||||
$value->execute($annotations['handler']);
|
||||
}
|
||||
foreach ($annotations['methods'] as $name => $attribute) {
|
||||
foreach ($attribute as $value) {
|
||||
if ($value instanceof Relation) {
|
||||
$annotation->addRelate($className, $value->name, $name);
|
||||
} else if ($value instanceof Get) {
|
||||
$annotation->addGets($className, $value->name, $name);
|
||||
} else if ($value instanceof Set) {
|
||||
$annotation->addSets($className, $value->name, $name);
|
||||
} else {
|
||||
$value->execute($annotations['handler'], $name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class LocalService
|
||||
* @package Annotation
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_CLASS)] class LocalService extends Attribute
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* LocalService constructor.
|
||||
* @param string $service
|
||||
* @param array|null $args
|
||||
* @param bool $async_reload
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct(public string $service, public ?array $args = [], public bool $async_reload = true)
|
||||
{
|
||||
if ($this->async_reload !== true) {
|
||||
return;
|
||||
}
|
||||
Event::on(Event::SERVER_WORKER_EXIT, function () {
|
||||
Snowflake::app()->remove($this->service);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param object $class
|
||||
* @param string $method
|
||||
* @return mixed
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): mixed
|
||||
{
|
||||
$class = ['class' => $class::class];
|
||||
if (!empty($this->args)) {
|
||||
$class = array_merge($class, $this->args);
|
||||
}
|
||||
|
||||
Snowflake::set($this->service, $class);
|
||||
return true; // TODO: Change the autogenerated stub
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation\Model;
|
||||
|
||||
|
||||
use Annotation\Annotation;
|
||||
use Attribute;
|
||||
use Database\ActiveRecord;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
|
||||
/**
|
||||
* Class Get
|
||||
* @package Annotation\Model
|
||||
*/
|
||||
#[Attribute(Attribute::TARGET_METHOD)] class Get extends \Annotation\Attribute
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Get constructor.
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct(public string $name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return ActiveRecord
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): bool
|
||||
{
|
||||
$annotation = Snowflake::getAnnotation();
|
||||
$annotation->addGets($class::class, $this->name, $method);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,41 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation\Model;
|
||||
|
||||
|
||||
use Annotation\Attribute;
|
||||
use Database\ActiveRecord;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
|
||||
/**
|
||||
* Class Relation
|
||||
* @package Annotation\Model
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)] class Relation extends Attribute
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Relation constructor.
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct(public string $name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return bool
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): bool
|
||||
{
|
||||
$annotation = Snowflake::getAnnotation();
|
||||
$annotation->addRelate($class::class, $this->name, $method);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation\Model;
|
||||
|
||||
|
||||
use Annotation\Attribute;
|
||||
use Database\ActiveRecord;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)] class Set extends Attribute
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Set constructor.
|
||||
* @param string $name
|
||||
*/
|
||||
public function __construct(public string $name)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mixed $class
|
||||
* @param mixed|null $method
|
||||
* @return bool
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): bool
|
||||
{
|
||||
$annotation = Snowflake::getAnnotation();
|
||||
$annotation->addSets($class::class, $this->name, $method);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
|
||||
/**
|
||||
* Class Port
|
||||
* @package Annotation
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_CLASS)] class Port extends Attribute
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Port constructor.
|
||||
* @param int $port
|
||||
* @param int $mode
|
||||
*/
|
||||
public function __construct(public int $port, public int $mode = SWOOLE_SOCK_TCP)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): mixed
|
||||
{
|
||||
$router = Snowflake::app()->getRouter();
|
||||
if (!($class instanceof Porters)) {
|
||||
return true;
|
||||
}
|
||||
$router->addPortListen($this->port, [$class, 'process']);
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation;
|
||||
|
||||
|
||||
interface Porters
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function process(): mixed;
|
||||
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation\Route;
|
||||
|
||||
|
||||
use Annotation\Attribute;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Interceptor
|
||||
* @package Annotation\Route
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)] class After extends Attribute
|
||||
{
|
||||
|
||||
/**
|
||||
* Interceptor constructor.
|
||||
* @param \HttpServer\IInterface\After|\HttpServer\IInterface\After[] $after
|
||||
* @throws
|
||||
*/
|
||||
public function __construct(public string|array $after)
|
||||
{
|
||||
if (is_string($this->after)) {
|
||||
$this->after = [$this->after];
|
||||
}
|
||||
foreach ($this->after as $key => $value) {
|
||||
$sn = Snowflake::createObject($value);
|
||||
if (!($sn instanceof \HttpServer\IInterface\After)) {
|
||||
continue;
|
||||
}
|
||||
$this->after[$key] = [$sn, 'onHandler'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mixed $class
|
||||
* @param mixed|null $method
|
||||
* @return After
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): static
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation\Route;
|
||||
|
||||
|
||||
use Annotation\Attribute;
|
||||
|
||||
/**
|
||||
* Class Document
|
||||
* @package Annotation\Route
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)] class Document extends Attribute
|
||||
{
|
||||
|
||||
const INTEGER = 'int';
|
||||
const STRING = 'string';
|
||||
const BOOLEAN = 'bool';
|
||||
const FLOAT = 'float';
|
||||
|
||||
const ALIAS = [
|
||||
self::INTEGER => '整数',
|
||||
self::STRING => '字符串',
|
||||
self::BOOLEAN => '布尔值',
|
||||
self::FLOAT => '浮点',
|
||||
];
|
||||
|
||||
|
||||
public function __construct(
|
||||
public array $request,
|
||||
public array $response
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return array
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): array
|
||||
{
|
||||
// TODO: Implement execute() method.
|
||||
return [$this->request, $this->response];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation\Route;
|
||||
|
||||
|
||||
use Annotation\Attribute;
|
||||
use Exception;
|
||||
use HttpServer\HttpFilter;
|
||||
use ReflectionException;
|
||||
use Snowflake\Exception\ComponentException;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Filter
|
||||
* @package Annotation\Route
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)] class Filter extends Attribute
|
||||
{
|
||||
|
||||
/**
|
||||
* Filter constructor.
|
||||
* @param array $rules
|
||||
*/
|
||||
public function __construct(public array $rules)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation\Route;
|
||||
|
||||
|
||||
use Annotation\Attribute;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Interceptor
|
||||
* @package Annotation\Route
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)] class Interceptor extends Attribute
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Interceptor constructor.
|
||||
* @param string|array $interceptor
|
||||
* @throws
|
||||
*/
|
||||
#[Pure] public function __construct(public string|array $interceptor)
|
||||
{
|
||||
if (is_string($this->interceptor)) {
|
||||
$this->interceptor = [$this->interceptor];
|
||||
}
|
||||
|
||||
foreach ($this->interceptor as $key => $value) {
|
||||
$sn = Snowflake::createObject($value);
|
||||
|
||||
if (!($sn instanceof \HttpServer\IInterface\Interceptor)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->interceptor[$key] = [$sn, 'Interceptor'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return Interceptor
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): static
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation\Route;
|
||||
|
||||
|
||||
use Annotation\Attribute;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Limits
|
||||
* @package Annotation\Route
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)] class Limits extends Attribute
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Limits constructor.
|
||||
* @param string|array $limits
|
||||
* @throws
|
||||
*/
|
||||
public function __construct(public string|array $limits)
|
||||
{
|
||||
if (is_string($this->limits)) {
|
||||
$this->limits = [$this->limits];
|
||||
}
|
||||
|
||||
foreach ($this->limits as $key => $value) {
|
||||
$sn = Snowflake::createObject($value);
|
||||
|
||||
if (!($sn instanceof \HttpServer\IInterface\Limits)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->limits[$key] = [$sn, 'next'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return Limits
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): static
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation\Route;
|
||||
|
||||
|
||||
use Annotation\Attribute;
|
||||
use Snowflake\Snowflake;
|
||||
use HttpServer\IInterface\Middleware as IMiddleware;
|
||||
|
||||
/**
|
||||
* Class Middleware
|
||||
* @package Annotation\Route
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)] class Middleware extends Attribute
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Interceptor constructor.
|
||||
* @param string|array $middleware
|
||||
* @throws
|
||||
*/
|
||||
public function __construct(public string|array $middleware)
|
||||
{
|
||||
if (is_string($this->middleware)) {
|
||||
$this->middleware = [$this->middleware];
|
||||
}
|
||||
|
||||
$array = [];
|
||||
foreach ($this->middleware as $key => $value) {
|
||||
$sn = Snowflake::createObject($value);
|
||||
if (!($sn instanceof IMiddleware)) {
|
||||
continue;
|
||||
}
|
||||
$array[] = [$sn, 'onHandler'];
|
||||
}
|
||||
$this->middleware = $array;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return Middleware
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): static
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation\Route;
|
||||
|
||||
|
||||
use Annotation\Attribute;
|
||||
use Exception;
|
||||
use HttpServer\Route\Router;
|
||||
use Snowflake\Exception\ConfigException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)] class Route extends Attribute
|
||||
{
|
||||
|
||||
/**
|
||||
* Route constructor.
|
||||
* @param string $uri
|
||||
* @param string $method
|
||||
* @param string $version
|
||||
*/
|
||||
public function __construct(
|
||||
public string $uri,
|
||||
public string $method,
|
||||
public string $version = 'v.1.0'
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return Router
|
||||
* @throws ConfigException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): Router
|
||||
{
|
||||
// TODO: Implement setHandler() method.
|
||||
$router = Snowflake::app()->getRouter();
|
||||
|
||||
$router->addRoute($this->uri, [$class, $method], $this->method);
|
||||
|
||||
return $router;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation\Route;
|
||||
|
||||
|
||||
use Annotation\Attribute;
|
||||
use Exception;
|
||||
use HttpServer\Http\Request;
|
||||
use HttpServer\Route\Router;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
|
||||
/**
|
||||
* Class RpcProducer
|
||||
* @package Annotation\Route
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)] class RpcProducer extends Attribute
|
||||
{
|
||||
|
||||
private string $uri = '';
|
||||
|
||||
const PROTOCOL_JSON = 'json';
|
||||
const PROTOCOL_SERIALIZE = 'serialize';
|
||||
|
||||
|
||||
/**
|
||||
* Route constructor.
|
||||
* @param string $cmd
|
||||
* @param string $protocol
|
||||
* @param int $port
|
||||
*/
|
||||
#[Pure] public function __construct(public string $cmd, public string $protocol = self::PROTOCOL_SERIALIZE, public int $port = 443)
|
||||
{
|
||||
$this->uri = 'rpc/p' . $this->port . '/' . ltrim($this->cmd, '/');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return Router
|
||||
* @throws Exception
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): Router
|
||||
{
|
||||
// TODO: Implement setHandler() method.
|
||||
$router = Snowflake::app()->getRouter();
|
||||
|
||||
$router->addRoute($this->uri, [$class, $method], Request::HTTP_CMD)
|
||||
->setDataType($this->protocol);
|
||||
|
||||
return $router;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation\Route;
|
||||
|
||||
|
||||
use Annotation\Attribute;
|
||||
use Exception;
|
||||
use HttpServer\Route\Router;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Socket
|
||||
* @package Annotation
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)] class Socket extends Attribute
|
||||
{
|
||||
|
||||
const CLOSE = 'CLOSE';
|
||||
const MESSAGE = 'MESSAGE';
|
||||
const HANDSHAKE = 'HANDSHAKE';
|
||||
|
||||
/**
|
||||
* Socket constructor.
|
||||
* @param string $event
|
||||
* @param string|null $uri
|
||||
* @param string $version
|
||||
*/
|
||||
public function __construct(public string $event, public ?string $uri = null, public string $version = 'v.1.0')
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mixed $class
|
||||
* @param mixed|null $method
|
||||
* @return Router
|
||||
* @throws Exception
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = null): Router
|
||||
{
|
||||
// TODO: Implement setHandler() method.
|
||||
$router = Snowflake::app()->getRouter();
|
||||
|
||||
$path = $this->event . '::' . (is_null($this->uri) ? 'event' : $this->uri);
|
||||
|
||||
$router->addRoute($path, [$class, $method], 'sw::socket');
|
||||
|
||||
return $router;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation\Rpc;
|
||||
|
||||
|
||||
use Annotation\Attribute;
|
||||
use Exception;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
|
||||
/**
|
||||
* Class Consumer
|
||||
* @package Annotation\Rpc
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_METHOD)] class Consumer extends Attribute
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Consumer constructor.
|
||||
* @param string $cmd
|
||||
*/
|
||||
public function __construct(public string $cmd)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = ''): mixed
|
||||
{
|
||||
$rpc = Snowflake::app()->getRpc();
|
||||
$rpc->addConsumer($this->cmd, [$class, $method]);
|
||||
return true; // TODO: Change the autogenerated stub
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation\Rpc;
|
||||
|
||||
|
||||
use Annotation\Attribute;
|
||||
use Exception;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
|
||||
/**
|
||||
* Class RpcClient
|
||||
* @package Annotation\Rpc
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_CLASS)] class RpcClient extends Attribute
|
||||
{
|
||||
|
||||
private array $config;
|
||||
|
||||
|
||||
/**
|
||||
* RpcClient constructor.
|
||||
* @param string $cmd
|
||||
* @param int $port
|
||||
* @param int $timeout
|
||||
* @param int $mode
|
||||
*/
|
||||
public function __construct(
|
||||
public string $cmd,
|
||||
public int $port,
|
||||
public int $timeout,
|
||||
public int $mode
|
||||
)
|
||||
{
|
||||
$this->config = ['port' => $port, 'mode' => $mode, 'timeout' => $timeout];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $handler
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function execute(mixed $class, mixed $method = ''): mixed
|
||||
{
|
||||
$rpc = Snowflake::app()->getRpc();
|
||||
$rpc->addProducer($this->cmd, [$class, $method], $this->config);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Annotation;
|
||||
|
||||
|
||||
/**
|
||||
* Class Target
|
||||
* @package Annotation
|
||||
*/
|
||||
#[\Attribute(\Attribute::TARGET_CLASS)] class Target extends Attribute
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Console;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Abstracts\Input;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class AbstractConsole
|
||||
* @package Console
|
||||
*/
|
||||
abstract class AbstractConsole extends Component
|
||||
{
|
||||
|
||||
/**
|
||||
* @var Command[]
|
||||
*/
|
||||
public array $commands = [];
|
||||
|
||||
/** @var Input $parameters */
|
||||
private Input $parameters;
|
||||
|
||||
/** @var array */
|
||||
private array $_config;
|
||||
|
||||
/**
|
||||
* @param array $config
|
||||
* AbstractConsole constructor.
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct(array $config = [])
|
||||
{
|
||||
$this->_config = $config;
|
||||
$this->signCommand(Snowflake::createObject(DefaultCommand::class));
|
||||
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Input $input
|
||||
* @return $this
|
||||
*/
|
||||
public function setParameters(Input $input): static
|
||||
{
|
||||
$this->parameters = $input;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Command $command
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function execCommand(Command $command): mixed
|
||||
{
|
||||
fire(Event::BEFORE_COMMAND_EXECUTE);
|
||||
|
||||
$data = $command->onHandler($this->parameters);
|
||||
|
||||
fire(Event::AFTER_COMMAND_EXECUTE, [$data]);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Command|null
|
||||
*/
|
||||
public function search(): ?Command
|
||||
{
|
||||
$name = $this->parameters->getCommandName();
|
||||
$this->parameters->set('commandList', $this->getCommandList());
|
||||
|
||||
$help = 'system:help';
|
||||
foreach ($this->commands as $command) {
|
||||
if ($command->command == $help) {
|
||||
$help = $command;
|
||||
}
|
||||
if ($command->command != $name) {
|
||||
continue;
|
||||
}
|
||||
return $command;
|
||||
}
|
||||
if (is_object($help)) {
|
||||
return $help;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Command $abstractConsole
|
||||
*
|
||||
* 注册命令
|
||||
*/
|
||||
public function signCommand(Command $abstractConsole)
|
||||
{
|
||||
$this->commands[] = $abstractConsole;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $kernel
|
||||
* @throws Exception
|
||||
*/
|
||||
public function batch($kernel)
|
||||
{
|
||||
if (is_object($kernel)) {
|
||||
if (!property_exists($kernel, 'commands')) {
|
||||
return;
|
||||
}
|
||||
$kernel = $kernel->commands;
|
||||
}
|
||||
if (!is_array($kernel)) {
|
||||
return;
|
||||
}
|
||||
foreach ($kernel as $command) {
|
||||
$this->signCommand(Snowflake::createObject($command));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Command $abstractConsole
|
||||
* 释放一个命令
|
||||
*/
|
||||
public function destroyCommand(Command $abstractConsole)
|
||||
{
|
||||
foreach ($this->commands as $index => $command) {
|
||||
if ($abstractConsole === $command) {
|
||||
unset($this->commands[$index]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
private function getCommandList(): array
|
||||
{
|
||||
$_tmp = [];
|
||||
foreach ($this->commands as $command) {
|
||||
if ($command->command === 'system:help') {
|
||||
continue;
|
||||
}
|
||||
$_tmp[$command->command] = [$command->description, $command];
|
||||
}
|
||||
ksort($_tmp, SORT_ASC);
|
||||
return $_tmp;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Console;
|
||||
|
||||
use ReflectionException;
|
||||
use Snowflake\Abstracts\BaseObject;
|
||||
use Snowflake\Abstracts\TraitApplication;
|
||||
use Snowflake\Exception\ComponentException;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Command
|
||||
* @package Console
|
||||
*/
|
||||
abstract class Command extends BaseObject implements CommandInterface
|
||||
{
|
||||
|
||||
use TraitApplication;
|
||||
|
||||
|
||||
public string $command = '';
|
||||
public string $description = '';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* 返回执行的命令名称
|
||||
*/
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->command;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*
|
||||
* 返回命令描述
|
||||
*/
|
||||
public function getDescription(): string
|
||||
{
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
* @throws ComponentException
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
public function __get($name): mixed
|
||||
{
|
||||
if ($this->has($name)) {
|
||||
return $this->get($name);
|
||||
}
|
||||
return parent::__get($name); // TODO: Change the autogenerated stub
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return bool
|
||||
*/
|
||||
private function has($name): bool
|
||||
{
|
||||
return Snowflake::app()->has($name);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
* @throws ReflectionException
|
||||
* @throws ComponentException
|
||||
* @throws NotFindClassException
|
||||
*/
|
||||
private function get($name): mixed
|
||||
{
|
||||
return Snowflake::app()->get($name);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Console;
|
||||
|
||||
use Snowflake\Abstracts\Input;
|
||||
|
||||
/**
|
||||
* Interface CommandInterface
|
||||
* @package Console
|
||||
*/
|
||||
interface CommandInterface
|
||||
{
|
||||
|
||||
public function onHandler(Input $dtl);
|
||||
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Console;
|
||||
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Console
|
||||
* @package Console
|
||||
*/
|
||||
class Console extends AbstractConsole
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param $class
|
||||
* @throws
|
||||
*/
|
||||
public function register($class)
|
||||
{
|
||||
if (is_string($class) || is_callable($class, true)) {
|
||||
$class = Snowflake::createObject($class);
|
||||
}
|
||||
$this->signCommand($class);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace Console;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Providers;
|
||||
use Snowflake\Application;
|
||||
|
||||
/**
|
||||
* Class ConsoleProviders
|
||||
* @package Console
|
||||
*/
|
||||
class ConsoleProviders extends Providers
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Application $application
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onImport(Application $application)
|
||||
{
|
||||
/** @var Console $console */
|
||||
$application->set('console', ['class' => Console::class]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Console;
|
||||
|
||||
use Snowflake\Abstracts\Input;
|
||||
|
||||
/**
|
||||
* Class DefaultCommand
|
||||
* @package Console
|
||||
*/
|
||||
class DefaultCommand extends Command
|
||||
{
|
||||
public string $command = 'system:help';
|
||||
|
||||
public string $description = 'command lists';
|
||||
|
||||
/**
|
||||
* @param Input $dtl
|
||||
* @return string
|
||||
*/
|
||||
public function onHandler(Input $dtl): string
|
||||
{
|
||||
$param = $dtl->get('commandList');
|
||||
|
||||
$last = '';
|
||||
$lists = ["Commands\t" . '注释'];
|
||||
foreach ($param as $key => $val) {
|
||||
$split = explode(':', $key);
|
||||
if (empty($last) && isset($split[0])) {
|
||||
$lists[] = "\033[32;40;1;1m" . $split[0] . " \033[0m\t";
|
||||
} else if (isset($split[0]) && $last != $split[0]) {
|
||||
$lists[] = "\033[32;40;1;1m" . $split[0] . " \033[0m\t";
|
||||
}
|
||||
|
||||
$last = $split[0] ?? '';
|
||||
|
||||
list($method, $ts) = $val;
|
||||
$lists[] = "\033[32;40;1;1m " . $key . " \033[0m\t\t" . $method."\t";
|
||||
}
|
||||
return implode(PHP_EOL, $lists);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Console;
|
||||
|
||||
|
||||
use Snowflake\Abstracts\Input;
|
||||
|
||||
interface ICommand
|
||||
{
|
||||
|
||||
public function onHandler(Input $dtl);
|
||||
|
||||
}
|
||||
@@ -1,327 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/4 0004
|
||||
* Time: 14:42
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database;
|
||||
|
||||
use Database\Traits\QueryTrait;
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class ActiveQuery
|
||||
* @package Database
|
||||
*/
|
||||
class ActiveQuery extends Component implements ISqlBuilder
|
||||
{
|
||||
|
||||
use QueryTrait;
|
||||
|
||||
/** @var array */
|
||||
public array $with = [];
|
||||
|
||||
/** @var bool */
|
||||
public bool $asArray = FALSE;
|
||||
|
||||
/** @var bool */
|
||||
public bool $useCache = FALSE;
|
||||
|
||||
/**
|
||||
* @var Connection|null
|
||||
*/
|
||||
public ?Connection $db = NULL;
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* 参数绑定
|
||||
*/
|
||||
public array $attributes = [];
|
||||
|
||||
|
||||
private SqlBuilder $builder;
|
||||
|
||||
|
||||
/**
|
||||
* Comply constructor.
|
||||
* @param $model
|
||||
* @param array $config
|
||||
* @throws
|
||||
*/
|
||||
public function __construct($model, $config = [])
|
||||
{
|
||||
$this->modelClass = $model;
|
||||
|
||||
$this->builder = SqlBuilder::builder($this);
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 清除不完整数据
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->db = null;
|
||||
$this->useCache = false;
|
||||
$this->with = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $value
|
||||
* @return $this
|
||||
*/
|
||||
public function addParam($key, $value): static
|
||||
{
|
||||
$this->attributes[$key] = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $values
|
||||
* @return $this
|
||||
*/
|
||||
public function addParams(array $values): static
|
||||
{
|
||||
foreach ($values as $key => $val) {
|
||||
$this->addParam($key, $val);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return $this
|
||||
*/
|
||||
public function with($name): static
|
||||
{
|
||||
if (empty($name)) {
|
||||
return $this;
|
||||
}
|
||||
if (is_string($name)) {
|
||||
$name = explode(',', $name);
|
||||
}
|
||||
foreach ($name as $key => $val) {
|
||||
array_push($this->with, $val);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isArray
|
||||
* @return $this
|
||||
*/
|
||||
public function asArray($isArray = TRUE): static
|
||||
{
|
||||
$this->asArray = $isArray;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $sql
|
||||
* @param array $params
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function execute($sql, $params = []): Command
|
||||
{
|
||||
return $this->modelClass::getDb()->createCommand($sql, $this->modelClass::getDbName(), $params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return ActiveRecord|array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function first(): ActiveRecord|array|null
|
||||
{
|
||||
$data = $this->execute($this->builder->one())->one();
|
||||
if (empty($data)) {
|
||||
return NULL;
|
||||
}
|
||||
$newModel = $this->modelClass::populate($data);
|
||||
if ($this->asArray) {
|
||||
return $newModel->toArray();
|
||||
}
|
||||
return $newModel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function toSql(): string
|
||||
{
|
||||
return $this->builder->get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array|Collection
|
||||
*/
|
||||
public function get(): Collection|array
|
||||
{
|
||||
return $this->all();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function flush(): array|bool|int|string|null
|
||||
{
|
||||
return $this->execute($this->builder->truncate())->exec();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $size
|
||||
* @param callable $callback
|
||||
* @return Pagination
|
||||
* @throws Exception
|
||||
*/
|
||||
public function page(int $size, callable $callback): Pagination
|
||||
{
|
||||
$pagination = new Pagination($this);
|
||||
$pagination->setOffset(0);
|
||||
$pagination->setLimit($size);
|
||||
$pagination->setCallback($callback);
|
||||
return $pagination;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
* @param string $setKey
|
||||
*
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function column(string $field, $setKey = ''): ?array
|
||||
{
|
||||
return $this->all()->column($field, $setKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|Collection
|
||||
* @throws
|
||||
*/
|
||||
public function all(): Collection|array
|
||||
{
|
||||
$data = $this->execute($this->builder->all())->all();
|
||||
|
||||
$collect = new Collection($this, $data, $this->modelClass);
|
||||
if ($this->asArray) {
|
||||
return $collect->toArray();
|
||||
}
|
||||
return $collect;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ActiveRecord $model
|
||||
* @param $data
|
||||
* @return ActiveRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
public function populate(ActiveRecord $model, $data): ActiveRecord
|
||||
{
|
||||
return $this->getWith($model::populate($data));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ActiveRecord $model
|
||||
* @return ActiveRecord
|
||||
*/
|
||||
public function getWith(ActiveRecord $model): ActiveRecord
|
||||
{
|
||||
if (empty($this->with) || !is_array($this->with)) {
|
||||
return $model;
|
||||
}
|
||||
return $model->setWith($this->with);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
$this->select = ['COUNT(*)'];
|
||||
$data = $this->execute($this->builder->count())->one();
|
||||
if ($data && is_array($data)) {
|
||||
return (int)array_shift($data);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return array|Command|bool|int|string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function batchUpdate(array $data): Command|array|bool|int|string
|
||||
{
|
||||
$generate = $this->builder->update($data);
|
||||
if (is_bool($generate)) {
|
||||
return $generate;
|
||||
}
|
||||
return $this->execute(...$generate)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function batchInsert(array $data): bool
|
||||
{
|
||||
[$sql, $params] = $this->builder->insert($data, true);
|
||||
|
||||
|
||||
return $this->execute($sql, $params)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $filed
|
||||
*
|
||||
* @return null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function value($filed)
|
||||
{
|
||||
return $this->first()[$filed] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function exists(): bool
|
||||
{
|
||||
return !empty($this->execute($this->builder->one())->fetchColumn());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param bool $getSql
|
||||
* @return string|bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function delete($getSql = false): string|bool
|
||||
{
|
||||
$sql = $this->builder->delete();
|
||||
if ($getSql === false) {
|
||||
return $this->execute($sql)->delete();
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
}
|
||||
@@ -1,442 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/3/30 0030
|
||||
* Time: 14:39
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
use Database\Base\BaseActiveRecord;
|
||||
use Database\Traits\HasBase;
|
||||
use Exception;
|
||||
use ReflectionException;
|
||||
use Snowflake\Channel;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
defined('SAVE_FAIL') or define('SAVE_FAIL', 3227);
|
||||
defined('FIND_OR_CREATE_MESSAGE') or define('FIND_OR_CREATE_MESSAGE', 'Create a new model, but the data cannot be empty.');
|
||||
|
||||
/**
|
||||
* Class Orm
|
||||
* @package Database
|
||||
*
|
||||
* @property $attributes
|
||||
* @property-read $oldAttributes
|
||||
* @method beforeSearch($model)
|
||||
*/
|
||||
class ActiveRecord extends BaseActiveRecord
|
||||
{
|
||||
|
||||
const DECR = 'decr';
|
||||
const INCR = 'incr';
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return ActiveRecord|false
|
||||
* @throws Exception
|
||||
*/
|
||||
public function increment(string $column, int $value): bool|ActiveRecord
|
||||
{
|
||||
if (!$this->mathematics([$column => $value], '+')) {
|
||||
return false;
|
||||
}
|
||||
$this->{$column} += $value;
|
||||
return $this->refresh();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return ActiveRecord|false
|
||||
* @throws Exception
|
||||
*/
|
||||
public function decrement(string $column, int $value): bool|ActiveRecord
|
||||
{
|
||||
if (!$this->mathematics([$column => $value], '-')) {
|
||||
return false;
|
||||
}
|
||||
$this->{$column} -= $value;
|
||||
return $this->refresh();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $columns
|
||||
* @return ActiveRecord|false
|
||||
* @throws Exception
|
||||
*/
|
||||
public function increments(array $columns): bool|static
|
||||
{
|
||||
if (!$this->mathematics($columns, '+')) {
|
||||
return false;
|
||||
}
|
||||
foreach ($columns as $key => $attribute) {
|
||||
$this->$key += $attribute;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $columns
|
||||
* @return ActiveRecord|false
|
||||
* @throws Exception
|
||||
*/
|
||||
public function decrements(array $columns): bool|static
|
||||
{
|
||||
if (!$this->mathematics($columns, '-')) {
|
||||
return false;
|
||||
}
|
||||
foreach ($columns as $key => $attribute) {
|
||||
$this->$key -= $attribute;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $condition
|
||||
* @param array $attributes
|
||||
* @return bool|ActiveRecord
|
||||
* @throws ReflectionException
|
||||
* @throws NotFindClassException
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function findOrCreate(array $condition, array $attributes = []): bool|static
|
||||
{
|
||||
$logger = Snowflake::app()->getLogger();
|
||||
|
||||
/** @var static $select */
|
||||
$select = static::find()->where($condition)->first();
|
||||
if (!empty($select)) {
|
||||
return $select;
|
||||
}
|
||||
if (empty($attributes)) {
|
||||
return $logger->addError(FIND_OR_CREATE_MESSAGE, 'mysql');
|
||||
}
|
||||
$select = self::getModelClass();
|
||||
$select->attributes = $attributes;
|
||||
if (!$select->save()) {
|
||||
return $logger->addError($select->getLastError(), 'mysql');
|
||||
}
|
||||
return $select;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $condition
|
||||
* @param array $attributes
|
||||
* @return bool|static
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function createOrUpdate(array $condition, array $attributes = []): bool|static
|
||||
{
|
||||
$logger = Snowflake::app()->getLogger();
|
||||
if (empty($attributes)) {
|
||||
return $logger->addError(FIND_OR_CREATE_MESSAGE, 'mysql');
|
||||
}
|
||||
/** @var static $select */
|
||||
$select = static::find()->where($condition)->first();
|
||||
if (empty($select)) {
|
||||
$select = self::getModelClass();
|
||||
}
|
||||
$select->attributes = $attributes;
|
||||
if (!$select->save()) {
|
||||
return $logger->addError($select->getLastError(), 'mysql');
|
||||
}
|
||||
return $select;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return static
|
||||
* @throws Exception
|
||||
*/
|
||||
private static function getModelClass(): static
|
||||
{
|
||||
/** @var Channel $channel */
|
||||
$channel = Snowflake::app()->get('channel');
|
||||
return $channel->pop(static::class, function () {
|
||||
return new static();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $action
|
||||
* @param $columns
|
||||
* @param array $condition
|
||||
* @return array|bool|int|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
private function mathematics($columns, $action, $condition = []): int|bool|array|string|null
|
||||
{
|
||||
if (empty($condition)) {
|
||||
$condition = [$this->getPrimary() => $this->getPrimaryValue()];
|
||||
}
|
||||
|
||||
$activeQuery = static::find()->where($condition);
|
||||
$create = SqlBuilder::builder($activeQuery)->mathematics($columns, $action);
|
||||
if (is_bool($create)) {
|
||||
return false;
|
||||
}
|
||||
return static::getDb()->createCommand($create[0], static::getDbName(), $create[1])->exec();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $fields
|
||||
* @return ActiveRecord|bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function update(array $fields): static|bool
|
||||
{
|
||||
return $this->save($fields);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function inserts(array $data): bool
|
||||
{
|
||||
/** @var static $class */
|
||||
$class = Snowflake::createObject(['class' => static::class]);
|
||||
if (empty($data)) {
|
||||
return $class->addError('Insert data empty.', 'mysql');
|
||||
}
|
||||
return $class::find()->batchInsert($data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function delete(): bool
|
||||
{
|
||||
$conditions = $this->_oldAttributes;
|
||||
if (empty($conditions)) {
|
||||
return $this->addError("Delete condition do not empty.", 'mysql');
|
||||
}
|
||||
$primary = $this->getPrimary();
|
||||
|
||||
if (!empty($primary)) {
|
||||
$conditions = [$primary => $this->getAttribute($primary)];
|
||||
}
|
||||
return static::deleteByCondition($conditions);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $condition
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function updateAll(mixed $condition, $attributes = []): bool
|
||||
{
|
||||
$condition = static::find()->where($condition);
|
||||
return $condition->batchUpdate($attributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $condition
|
||||
* @param array $attributes
|
||||
*
|
||||
* @return array|Collection
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function findAll($condition, $attributes = []): array|Collection
|
||||
{
|
||||
$query = static::find()->where($condition);
|
||||
if (!empty($attributes)) {
|
||||
$query->bindParams($attributes);
|
||||
}
|
||||
return $query->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $method
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
private function resolveObject($method): mixed
|
||||
{
|
||||
$resolve = $this->{$this->getRelate($method)}();
|
||||
if ($resolve instanceof HasBase) {
|
||||
$resolve = $resolve->get();
|
||||
}
|
||||
if ($resolve instanceof Collection) {
|
||||
return $resolve->toArray();
|
||||
} else if ($resolve instanceof ActiveRecord) {
|
||||
return $resolve->toArray();
|
||||
} else if (is_object($resolve)) {
|
||||
return get_object_vars($resolve);
|
||||
} else {
|
||||
return $resolve;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
$data = $this->_attributes;
|
||||
|
||||
$lists = Snowflake::getAnnotation()->getGets(static::class);
|
||||
foreach ($lists as $key => $item) {
|
||||
$data[$key] = $this->{$item}($data[$key] ?? null);
|
||||
}
|
||||
$data = array_merge($data, $this->runRelate());
|
||||
|
||||
$class = Snowflake::app()->getChannel();
|
||||
$class->push($this, static::class);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function runRelate(): array
|
||||
{
|
||||
$relates = [];
|
||||
if (empty($with = $this->getWith())) {
|
||||
return $relates;
|
||||
}
|
||||
foreach ($with as $val) {
|
||||
$relates[$val] = $this->resolveObject($val);
|
||||
}
|
||||
return $relates;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $modelName
|
||||
* @param $foreignKey
|
||||
* @param $localKey
|
||||
* @return HasOne|ActiveQuery
|
||||
* @throws Exception
|
||||
*/
|
||||
public function hasOne(string $modelName, $foreignKey, $localKey): HasOne|ActiveQuery
|
||||
{
|
||||
if (($value = $this->getAttribute($localKey)) === null) {
|
||||
throw new Exception("Need join table primary key.");
|
||||
}
|
||||
|
||||
$relation = $this->getRelation();
|
||||
|
||||
return new HasOne($modelName, $foreignKey, $value, $relation);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $modelName
|
||||
* @param $foreignKey
|
||||
* @param $localKey
|
||||
* @return ActiveQuery
|
||||
* @throws Exception
|
||||
*/
|
||||
public function hasCount($modelName, $foreignKey, $localKey): mixed
|
||||
{
|
||||
if (($value = $this->getAttribute($localKey)) === null) {
|
||||
throw new Exception("Need join table primary key.");
|
||||
}
|
||||
|
||||
$relation = $this->getRelation();
|
||||
|
||||
return new HasCount($modelName, $foreignKey, $value, $relation);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $modelName
|
||||
* @param $foreignKey
|
||||
* @param $localKey
|
||||
* @return ActiveQuery
|
||||
* @throws Exception
|
||||
*/
|
||||
public function hasMany($modelName, $foreignKey, $localKey): mixed
|
||||
{
|
||||
if (($value = $this->getAttribute($localKey)) === null) {
|
||||
throw new Exception("Need join table primary key.");
|
||||
}
|
||||
|
||||
$relation = $this->getRelation();
|
||||
|
||||
return new HasMany($modelName, $foreignKey, $value, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $modelName
|
||||
* @param $foreignKey
|
||||
* @param $localKey
|
||||
* @return ActiveQuery
|
||||
* @throws Exception
|
||||
*/
|
||||
public function hasIn($modelName, $foreignKey, $localKey): mixed
|
||||
{
|
||||
if (($value = $this->getAttribute($localKey)) === null) {
|
||||
throw new Exception("Need join table primary key.");
|
||||
}
|
||||
|
||||
$relation = $this->getRelation();
|
||||
|
||||
return new HasMany($modelName, $foreignKey, $value, $relation);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function afterDelete(): bool
|
||||
{
|
||||
if (!$this->hasPrimary()) {
|
||||
return TRUE;
|
||||
}
|
||||
$value = $this->getPrimaryValue();
|
||||
if (empty($value)) {
|
||||
return TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function beforeDelete(): bool
|
||||
{
|
||||
if (!$this->hasPrimary()) {
|
||||
return TRUE;
|
||||
}
|
||||
$value = $this->getPrimaryValue();
|
||||
if (empty($value)) {
|
||||
return TRUE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/9 0009
|
||||
* Time: 9:44
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Base;
|
||||
|
||||
|
||||
use ArrayIterator;
|
||||
use Database\ActiveQuery;
|
||||
use Database\ActiveRecord;
|
||||
use Exception;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Snowflake;
|
||||
use Traversable;
|
||||
|
||||
/**
|
||||
* Class AbstractCollection
|
||||
* @package Database\Base
|
||||
*/
|
||||
abstract class AbstractCollection extends Component implements \IteratorAggregate, \ArrayAccess
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ActiveRecord[]
|
||||
*/
|
||||
protected array $_item = [];
|
||||
|
||||
protected ActiveRecord|string|null $model;
|
||||
|
||||
protected ActiveQuery $query;
|
||||
|
||||
|
||||
public function clean()
|
||||
{
|
||||
unset($this->query, $this->model, $this->_item);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Collection constructor.
|
||||
*
|
||||
* @param $query
|
||||
* @param array $array
|
||||
* @param null|string|ActiveRecord $model
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct($query, array $array = [], $model = null)
|
||||
{
|
||||
$this->_item = $array;
|
||||
$this->query = $query;
|
||||
$this->model = $model;
|
||||
|
||||
parent::__construct([]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
#[Pure] public function getLength(): int
|
||||
{
|
||||
return count($this->_item);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $item
|
||||
*/
|
||||
public function setItems($item)
|
||||
{
|
||||
$this->_item = $item;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $model
|
||||
*/
|
||||
public function setModel($model)
|
||||
{
|
||||
$this->model = $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $item
|
||||
*/
|
||||
public function addItem($item)
|
||||
{
|
||||
array_push($this->_item, $item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Traversable|CollectionIterator|ArrayIterator
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getIterator(): Traversable|CollectionIterator|ArrayIterator
|
||||
{
|
||||
return new CollectionIterator($this->model, $this->query, $this->_item);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getModel(): ActiveRecord
|
||||
{
|
||||
if (!is_object($this->model)) {
|
||||
$this->model = $this->model::populate([]);
|
||||
$this->model->setIsCreate(false);
|
||||
}
|
||||
return $this->model;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists(mixed $offset): bool
|
||||
{
|
||||
return !empty($this->_item) && isset($this->_item[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @return ActiveRecord|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function offsetGet(mixed $offset): ?ActiveRecord
|
||||
{
|
||||
if (!$this->offsetExists($offset)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ($this->_item[$offset] instanceof ActiveRecord) {
|
||||
return $this->_item[$offset];
|
||||
}
|
||||
|
||||
return $this->model::populate($this->_item[$offset]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
* @param mixed $value
|
||||
*/
|
||||
public function offsetSet(mixed $offset, mixed $value)
|
||||
{
|
||||
$this->_item[$offset] = $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mixed $offset
|
||||
*/
|
||||
public function offsetUnset(mixed $offset)
|
||||
{
|
||||
if ($this->offsetExists($offset)) {
|
||||
unset($this->_item[$offset]);
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,75 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Base;
|
||||
|
||||
|
||||
use Database\ActiveQuery;
|
||||
use Database\ActiveRecord;
|
||||
use Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Class CollectionIterator
|
||||
* @package Database\Base
|
||||
*/
|
||||
class CollectionIterator extends \ArrayIterator
|
||||
{
|
||||
|
||||
private ActiveRecord|string $model;
|
||||
|
||||
|
||||
/** @var ActiveQuery */
|
||||
private ActiveQuery $query;
|
||||
|
||||
|
||||
private ?ActiveRecord $_clone = null;
|
||||
|
||||
|
||||
public function clean()
|
||||
{
|
||||
unset($this->query);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* CollectionIterator constructor.
|
||||
* @param $model
|
||||
* @param $query
|
||||
* @param array $array
|
||||
* @param int $flags
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct($model, $query, $array = array(), $flags = 0)
|
||||
{
|
||||
$this->model = $model;
|
||||
$this->query = $query;
|
||||
parent::__construct($array, $flags);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $current
|
||||
* @return ActiveRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function newModel($current): ActiveRecord
|
||||
{
|
||||
return $this->model::populate($current);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function current(): ActiveRecord
|
||||
{
|
||||
if (is_array($current = parent::current())) {
|
||||
$current = $this->newModel($current);
|
||||
}
|
||||
return $this->query->getWith($current);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
namespace Database\Base;
|
||||
|
||||
|
||||
use Database\Condition\BetweenCondition;
|
||||
use Database\Condition\InCondition;
|
||||
use Database\Condition\LikeCondition;
|
||||
use Database\Condition\LLikeCondition;
|
||||
use Database\Condition\MathematicsCondition;
|
||||
use Database\Condition\NotBetweenCondition;
|
||||
use Database\Condition\NotInCondition;
|
||||
use Database\Condition\NotLikeCondition;
|
||||
use Database\Condition\RLikeCondition;
|
||||
|
||||
/**
|
||||
* Class ConditionClassMap
|
||||
* @package Database\Base
|
||||
*/
|
||||
class ConditionClassMap
|
||||
{
|
||||
|
||||
public static array $conditionMap = [
|
||||
'IN' => [
|
||||
'class' => InCondition::class
|
||||
],
|
||||
'NOT IN' => [
|
||||
'class' => NotInCondition::class
|
||||
],
|
||||
'LIKE' => [
|
||||
'class' => LikeCondition::class
|
||||
],
|
||||
'NOT LIKE' => [
|
||||
'class' => NotLikeCondition::class
|
||||
],
|
||||
'LLike' => [
|
||||
'class' => LLikeCondition::class
|
||||
],
|
||||
'RLike' => [
|
||||
'class' => RLikeCondition::class
|
||||
],
|
||||
'EQ' => [
|
||||
'class' => MathematicsCondition::class,
|
||||
'type' => 'EQ'
|
||||
],
|
||||
'NEQ' => [
|
||||
'class' => MathematicsCondition::class,
|
||||
'type' => 'NEQ'
|
||||
],
|
||||
'GT' => [
|
||||
'class' => MathematicsCondition::class,
|
||||
'type' => 'GT'
|
||||
],
|
||||
'EGT' => [
|
||||
'class' => MathematicsCondition::class,
|
||||
'type' => 'EGT'
|
||||
],
|
||||
'LT' => [
|
||||
'class' => MathematicsCondition::class,
|
||||
'type' => 'LT'
|
||||
],
|
||||
'ELT' => [
|
||||
'class' => MathematicsCondition::class,
|
||||
'type' => 'ELT'
|
||||
],
|
||||
'BETWEEN' => BetweenCondition::class,
|
||||
'NOT BETWEEN' => NotBetweenCondition::class,
|
||||
];
|
||||
|
||||
}
|
||||
@@ -1,242 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/4 0004
|
||||
* Time: 13:38
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database;
|
||||
|
||||
use Database\Base\AbstractCollection;
|
||||
use Exception;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
|
||||
/**
|
||||
* Class Collection
|
||||
* @package Database
|
||||
* @property-read $length
|
||||
*/
|
||||
class Collection extends AbstractCollection
|
||||
{
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getItems(): array
|
||||
{
|
||||
// TODO: Change the autogenerated stub
|
||||
return $this->_item;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
*
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function values($field): ?array
|
||||
{
|
||||
if (empty($field) || !is_string($field)) {
|
||||
return NULL;
|
||||
}
|
||||
$_tmp = [];
|
||||
$data = $this->toArray();
|
||||
foreach ($data as $val) {
|
||||
/** @var ActiveRecord $val */
|
||||
$_tmp[] = $val[$field];
|
||||
}
|
||||
return $_tmp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
* @return array|null
|
||||
*/
|
||||
public function keyBy(string $field): ?array
|
||||
{
|
||||
$array = $this->toArray();
|
||||
$column = array_flip(array_column($array, $field));
|
||||
foreach ($column as $key => $value) {
|
||||
$column[$key] = $array[$value];
|
||||
}
|
||||
|
||||
return $column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function orderRand(): static
|
||||
{
|
||||
shuffle($this->_item);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $start
|
||||
* @param int $length
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
#[Pure] public function slice($start = 0, $length = 20): array
|
||||
{
|
||||
if (empty($this->_item) || !is_array($this->_item)) {
|
||||
return [];
|
||||
}
|
||||
if (count($this->_item) < $length) {
|
||||
return $this->_item;
|
||||
} else {
|
||||
return array_slice($this->_item, $start, $length);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
* @param string $setKey
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public function column($field, $setKey = ''): ?array
|
||||
{
|
||||
$data = $this->toArray();
|
||||
if (empty($data)) {
|
||||
return [];
|
||||
}
|
||||
if (!empty($setKey) && is_string($setKey)) {
|
||||
return array_column($data, $field, $setKey);
|
||||
} else {
|
||||
return array_column($data, $field);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
*
|
||||
* @return float|int|null
|
||||
*/
|
||||
public function sum($field): float|int|null
|
||||
{
|
||||
$array = $this->column($field);
|
||||
if (empty($array)) {
|
||||
return NULL;
|
||||
}
|
||||
return array_sum($array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ActiveRecord|array
|
||||
*/
|
||||
#[Pure] public function current(): ActiveRecord|array
|
||||
{
|
||||
return current($this->_item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
#[Pure] public function size(): int
|
||||
{
|
||||
return (int)count($this->_item);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws
|
||||
*/
|
||||
public function toArray(): array
|
||||
{
|
||||
$array = [];
|
||||
foreach ($this as $value) {
|
||||
if (!is_object($value)) {
|
||||
continue;
|
||||
}
|
||||
$array[] = $value->toArray();
|
||||
}
|
||||
$this->_item = [];
|
||||
return $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* 批量删除
|
||||
*/
|
||||
public function delete(): bool
|
||||
{
|
||||
$model = $this->getModel();
|
||||
if (!$model->hasPrimary()) return false;
|
||||
$ids = [];
|
||||
foreach ($this as $item) {
|
||||
$id = $item->getPrimaryValue();
|
||||
if (!empty($id)) {
|
||||
$ids[] = $id;
|
||||
}
|
||||
}
|
||||
return $model::find()->in($model->getPrimary(), $ids)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $condition
|
||||
* @return Collection
|
||||
* @throws
|
||||
*/
|
||||
public function filter(array $condition): Collection|static
|
||||
{
|
||||
$_filters = [];
|
||||
if (empty($condition)) {
|
||||
return $this;
|
||||
}
|
||||
foreach ($this as $value) {
|
||||
if (!$this->filterCheck($value, $condition)) {
|
||||
continue;
|
||||
}
|
||||
$_filters[] = $value;
|
||||
}
|
||||
return new Collection($this->query, $_filters, $this->model);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @param $condition
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
private function filterCheck($value, $condition): bool
|
||||
{
|
||||
$_value = $value;
|
||||
if ($_value instanceof ActiveRecord) {
|
||||
$_value = $_value->toArray();
|
||||
}
|
||||
$_tmp = array_intersect_key($_value, $condition);
|
||||
if (count(array_diff_assoc($_tmp, $condition)) > 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function exists($key, $value): mixed
|
||||
{
|
||||
foreach ($this as $item) {
|
||||
if ($item->$key === $value) {
|
||||
return $item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
#[Pure] public function isEmpty(): bool
|
||||
{
|
||||
return $this->size() < 1;
|
||||
}
|
||||
}
|
||||
@@ -1,316 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/3/30 0030
|
||||
* Time: 15:23
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
use Exception;
|
||||
use PDO;
|
||||
use PDOStatement;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Core\Json;
|
||||
|
||||
/**
|
||||
* Class Command
|
||||
* @package Database
|
||||
*/
|
||||
class Command extends Component
|
||||
{
|
||||
const ROW_COUNT = 'ROW_COUNT';
|
||||
const FETCH = 'FETCH';
|
||||
const FETCH_ALL = 'FETCH_ALL';
|
||||
const EXECUTE = 'EXECUTE';
|
||||
const FETCH_COLUMN = 'FETCH_COLUMN';
|
||||
|
||||
const DB_ERROR_MESSAGE = 'The system is busy, please try again later.';
|
||||
|
||||
/** @var Connection */
|
||||
public Connection $db;
|
||||
|
||||
/** @var ?string */
|
||||
public ?string $sql = '';
|
||||
|
||||
/** @var array */
|
||||
public array $params = [];
|
||||
|
||||
/** @var string */
|
||||
private string $_modelName;
|
||||
|
||||
private ?PDOStatement $prepare = null;
|
||||
|
||||
|
||||
/**
|
||||
* @return array|bool|int|string|PDOStatement|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function incrOrDecr(): array|bool|int|string|PDOStatement|null
|
||||
{
|
||||
return $this->execute(static::EXECUTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isInsert
|
||||
* @param mixed $hasAutoIncrement
|
||||
* @return int|bool|array|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function save(bool $isInsert = TRUE, mixed $hasAutoIncrement = null): int|bool|array|string|null
|
||||
{
|
||||
return $this->execute(static::EXECUTE, $isInsert, $hasAutoIncrement);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int|bool|array|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function all(): int|bool|array|string|null
|
||||
{
|
||||
return $this->execute(static::FETCH_ALL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|bool|int|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function one(): null|array|bool|int|string
|
||||
{
|
||||
return $this->execute(static::FETCH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|bool|array|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function fetchColumn(): int|bool|array|string|null
|
||||
{
|
||||
return $this->execute(static::FETCH_COLUMN);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|bool|array|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function rowCount(): int|bool|array|string|null
|
||||
{
|
||||
return $this->execute(static::ROW_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|bool|array|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function flush(): int|bool|array|string|null
|
||||
{
|
||||
return $this->execute(static::EXECUTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @param null $isInsert
|
||||
* @param bool|null $hasAutoIncrement
|
||||
* @return int|bool|array|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
private function execute($type, $isInsert = null, mixed $hasAutoIncrement = null): int|bool|array|string|null
|
||||
{
|
||||
try {
|
||||
$time = microtime(true);
|
||||
if ($type === static::EXECUTE) {
|
||||
$result = $this->insert_or_change($isInsert, $hasAutoIncrement);
|
||||
} else {
|
||||
$result = $this->search($type);
|
||||
}
|
||||
if (microtime(true) - $time >= 0.02) {
|
||||
$this->warning('Mysql:' . Json::encode([$this->sql, $this->params]) . (microtime(true) - $time));
|
||||
}
|
||||
if ($this->prepare) {
|
||||
$this->prepare->closeCursor();
|
||||
}
|
||||
return $result;
|
||||
} catch (\Throwable $exception) {
|
||||
return $this->addError($this->sql . '. error: ' . $exception->getMessage(), 'mysql');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
private function search($type): mixed
|
||||
{
|
||||
if (($prepare = $this->prepare()) == false) {
|
||||
return false;
|
||||
}
|
||||
if ($type === static::FETCH_COLUMN) {
|
||||
$data = $prepare->fetchAll(PDO::FETCH_ASSOC);
|
||||
} else if ($type === static::ROW_COUNT) {
|
||||
$data = $prepare->rowCount();
|
||||
} else if ($type === static::FETCH_ALL) {
|
||||
$data = $prepare->fetchAll(PDO::FETCH_ASSOC);
|
||||
} else {
|
||||
$data = $prepare->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
$prepare->closeCursor();
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $isInsert
|
||||
* @param $hasAutoIncrement
|
||||
* @return bool|string|int
|
||||
* @throws Exception
|
||||
*/
|
||||
private function insert_or_change($isInsert, $hasAutoIncrement): bool|string|int
|
||||
{
|
||||
if (($result = $this->getPdoStatement()) === false) {
|
||||
return $result;
|
||||
}
|
||||
if ($isInsert === false || !$hasAutoIncrement) {
|
||||
return true;
|
||||
}
|
||||
if ($result == 0 && $hasAutoIncrement->isAutoIncrement()) {
|
||||
return $this->addError(static::DB_ERROR_MESSAGE, 'mysql');
|
||||
}
|
||||
return $result == 0 ? true : $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 重新构建
|
||||
* @throws
|
||||
*/
|
||||
private function getPdoStatement(): bool|int
|
||||
{
|
||||
if (empty($this->sql)) {
|
||||
return $this->addError('no sql.', 'mysql');
|
||||
}
|
||||
if (!(($connect = $this->db->getConnect($this->sql)) instanceof PDO)) {
|
||||
return $this->addError('get client error.', 'mysql');
|
||||
}
|
||||
if (!(($prepare = $connect->prepare($this->sql)) instanceof PDOStatement)) {
|
||||
return $this->addError($this->errorMessage($prepare), 'mysql');
|
||||
}
|
||||
$result = $this->checkResponse($prepare, $connect);
|
||||
$prepare->closeCursor();
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $prepare
|
||||
* @return string
|
||||
*/
|
||||
private function errorMessage($prepare): string
|
||||
{
|
||||
return $this->sql . ':' . ($prepare->errorInfo()[2] ?? static::DB_ERROR_MESSAGE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool|\PDOStatement
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function prepare(): bool|PDOStatement
|
||||
{
|
||||
if (!(($connect = $this->db->getConnect($this->sql)) instanceof PDO)) {
|
||||
return $this->addError('get client error.', 'mysql');
|
||||
}
|
||||
if (!(($prepare = $connect->query($this->sql)) instanceof PDOStatement)) {
|
||||
$error = $prepare->errorInfo()[2] ?? static::DB_ERROR_MESSAGE;
|
||||
return $this->addError($this->sql . ':' . $error, 'mysql');
|
||||
}
|
||||
return $prepare;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $prepare
|
||||
* @param $connect
|
||||
* @return bool|int
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function checkResponse($prepare, $connect): bool|int
|
||||
{
|
||||
$result = $prepare->execute($this->params);
|
||||
if ($result === false) {
|
||||
return $this->addError($connect->errorInfo()[2], 'mysql');
|
||||
}
|
||||
return (int)$connect->lastInsertId();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $modelName
|
||||
* @return $this
|
||||
*/
|
||||
public function setModelName($modelName): static
|
||||
{
|
||||
$this->_modelName = $modelName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getModelName(): string
|
||||
{
|
||||
return $this->_modelName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int|bool|array|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function delete(): int|bool|array|string|null
|
||||
{
|
||||
return $this->execute(static::EXECUTE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $scope
|
||||
* @param bool $insert
|
||||
* @return int|bool|array|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function exec($scope = null, bool $insert = false): int|bool|array|string|null
|
||||
{
|
||||
return $this->execute(static::EXECUTE, $insert, $scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
* @return $this
|
||||
*/
|
||||
public function bindValues(array $data = []): static
|
||||
{
|
||||
if (!is_array($this->params)) {
|
||||
$this->params = [];
|
||||
}
|
||||
if (!empty($data)) {
|
||||
$this->params = array_merge($this->params, $data);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sql
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setSql($sql): static
|
||||
{
|
||||
$this->sql = $sql;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
|
||||
/**
|
||||
* Class BetweenCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class BetweenCondition extends Condition
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder(): string
|
||||
{
|
||||
return $this->column . ' BETWEEN ' . (int)$this->value[0] . ' AND ' . (int)$this->value[1];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
|
||||
/**
|
||||
* Class ChildCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class ChildCondition extends Condition
|
||||
{
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder(): string
|
||||
{
|
||||
return $this->column . ' ' . $this->opera . ' (' . $this->value . ')';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use Snowflake\Abstracts\BaseObject;
|
||||
use Snowflake\Core\Str;
|
||||
|
||||
/**
|
||||
* Class Condition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
abstract class Condition extends BaseObject
|
||||
{
|
||||
|
||||
protected string $column = '';
|
||||
protected string $opera = '=';
|
||||
|
||||
/** @var array|mixed */
|
||||
protected $value;
|
||||
|
||||
const INT_TYPE = ['bit', 'bool', 'tinyint', 'smallint', 'mediumint', 'int', 'bigint', 'float', 'double', 'decimal', 'timestamp'];
|
||||
|
||||
protected array $attributes = [];
|
||||
|
||||
abstract public function builder();
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
*/
|
||||
public function setColumn(string $column): void
|
||||
{
|
||||
$this->column = $column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $opera
|
||||
*/
|
||||
public function setOpera(string $opera): void
|
||||
{
|
||||
$this->opera = $opera;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $params
|
||||
*/
|
||||
public function setValue($params): void
|
||||
{
|
||||
if (is_array($params)) {
|
||||
$values = [];
|
||||
foreach ($params as $item => $value) {
|
||||
$values[$item] = is_numeric($value) ? $value : '\'' . $value . '\'';
|
||||
}
|
||||
$this->value = $values;
|
||||
} else {
|
||||
$this->value = $this->checkIsSqlString($params);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $params
|
||||
* @return int|string
|
||||
*/
|
||||
#[Pure] private function checkIsSqlString($params): int|string
|
||||
{
|
||||
if (is_numeric($params)) {
|
||||
return $params;
|
||||
}
|
||||
|
||||
$check = ltrim($params, '(');
|
||||
$check = strtolower(substr($check, 0, 6));
|
||||
if (in_array($check, ['update', 'select', 'insert', 'delete'])) {
|
||||
return $params;
|
||||
} else {
|
||||
return sprintf('\'%s\'', $params);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
|
||||
/**
|
||||
* Class DefaultCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class DefaultCondition extends Condition
|
||||
{
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
#[Pure] public function builder(): string
|
||||
{
|
||||
return sprintf('%s %s %s', $this->column, $this->opera, addslashes($this->value));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
/**
|
||||
* Class HashCondition
|
||||
* @package Yoc\db\condition
|
||||
*/
|
||||
class HashCondition extends Condition
|
||||
{
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder(): string
|
||||
{
|
||||
$array = [];
|
||||
if (empty($this->value)) {
|
||||
return '';
|
||||
}
|
||||
foreach ($this->value as $key => $value) {
|
||||
if ($value === null) {
|
||||
continue;
|
||||
}
|
||||
$array[] = sprintf("%s = '%s'", $key, addslashes($value));
|
||||
}
|
||||
return implode(' AND ', $array);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
use Database\ActiveQuery;
|
||||
use Exception;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
|
||||
/**
|
||||
* Class InCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class InCondition extends Condition
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
#[Pure] public function builder(): string
|
||||
{
|
||||
if (is_array($this->value)) {
|
||||
return sprintf('%s IN (%s)', $this->column, implode(',', $this->value));
|
||||
} else {
|
||||
return sprintf('%s IN (%s)', $this->column, $this->value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
|
||||
/**
|
||||
* Class JsonCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class JsonCondition extends Condition
|
||||
{
|
||||
|
||||
|
||||
public function builder()
|
||||
{
|
||||
// TODO: Implement builder() method.
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
use Snowflake\Core\Str;
|
||||
|
||||
/**
|
||||
* Class LLikeCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class LLikeCondition extends Condition
|
||||
{
|
||||
|
||||
public string $pos = '';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder(): string
|
||||
{
|
||||
if (!is_string($this->value)) {
|
||||
$this->value = array_shift($this->value);
|
||||
}
|
||||
return $this->column . ' LIKE \'%' . addslashes($this->value) . '\'';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
use Snowflake\Core\Str;
|
||||
|
||||
/**
|
||||
* Class LikeCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class LikeCondition extends Condition
|
||||
{
|
||||
|
||||
public string $pos = '';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder(): string
|
||||
{
|
||||
if (!is_string($this->value)) {
|
||||
$this->value = array_shift($this->value);
|
||||
}
|
||||
return $this->column . ' LIKE \'%' . addslashes($this->value) . '%\'';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
/**
|
||||
* Class MathematicsCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class MathematicsCondition extends Condition
|
||||
{
|
||||
|
||||
public string $type = '';
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function builder(): mixed
|
||||
{
|
||||
return $this->{strtolower($this->type)}((float)$this->value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @return string
|
||||
*/
|
||||
public function eq($value): string
|
||||
{
|
||||
return $this->column . ' = ' . $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @return string
|
||||
*/
|
||||
public function neq($value): string
|
||||
{
|
||||
return $this->column . ' <> ' . $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @return string
|
||||
*/
|
||||
public function gt($value): string
|
||||
{
|
||||
return $this->column . ' > ' . $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @return string
|
||||
*/
|
||||
public function egt($value): string
|
||||
{
|
||||
return $this->column . ' >= ' . $value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @return string
|
||||
*/
|
||||
public function lt($value): string
|
||||
{
|
||||
return $this->column . ' < ' . $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @return string
|
||||
*/
|
||||
public function elt($value): string
|
||||
{
|
||||
return $this->column . ' <= ' . $value;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
/**
|
||||
* Class NotBetweenCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class NotBetweenCondition extends Condition
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder(): string
|
||||
{
|
||||
return $this->column . ' NOT BETWEEN ' . (int)$this->value[0] . ' AND ' . (int)$this->value[1];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
|
||||
/**
|
||||
* Class NotInCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class NotInCondition extends Condition
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @return string|null
|
||||
*/
|
||||
#[Pure] public function builder(): ?string
|
||||
{
|
||||
if (!is_array($this->value)) {
|
||||
return null;
|
||||
}
|
||||
$value = '\'' . implode('\',\'', $this->value) . '\'';
|
||||
return '`' . $this->column . '` not in(' . $value . ')';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
use Snowflake\Core\Str;
|
||||
|
||||
/**
|
||||
* Class NotLikeCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class NotLikeCondition extends Condition
|
||||
{
|
||||
|
||||
public string $pos = '';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder(): string
|
||||
{
|
||||
if (!is_string($this->value)) {
|
||||
$this->value = array_shift($this->value);
|
||||
}
|
||||
return $this->column . ' NOT LIKE \'%' . addslashes($this->value) . '%\'';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
|
||||
/**
|
||||
* Class OrCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class OrCondition extends Condition
|
||||
{
|
||||
|
||||
public array $oldParams = [];
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
#[Pure] public function builder(): string
|
||||
{
|
||||
return sprintf('(%s) OR %s', implode(' AND ', $this->oldParams), addslashes($this->value));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Condition;
|
||||
|
||||
use Snowflake\Core\Str;
|
||||
|
||||
/**
|
||||
* Class RLikeCondition
|
||||
* @package Database\Condition
|
||||
*/
|
||||
class RLikeCondition extends Condition
|
||||
{
|
||||
|
||||
public string $pos = '';
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function builder(): string
|
||||
{
|
||||
if (!is_string($this->value)) {
|
||||
$this->value = array_shift($this->value);
|
||||
}
|
||||
return sprintf('%s LIKE \'%s\'', $this->column, addslashes($this->value));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,329 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/3/30 0030
|
||||
* Time: 14:09
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
use Database\Mysql\Schema;
|
||||
use Exception;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use PDO;
|
||||
use ReflectionException;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Abstracts\Config;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Connection
|
||||
* @package Database
|
||||
*/
|
||||
class Connection extends Component
|
||||
{
|
||||
const TRANSACTION_COMMIT = 'transaction::commit';
|
||||
const TRANSACTION_ROLLBACK = 'transaction::rollback';
|
||||
|
||||
public string $id = 'db';
|
||||
public string $cds = '';
|
||||
public string $password = '';
|
||||
public string $username = '';
|
||||
public string $charset = 'utf-8';
|
||||
public string $tablePrefix = '';
|
||||
|
||||
public string $database = '';
|
||||
|
||||
public int $timeout = 1900;
|
||||
|
||||
public int $maxNumber = 30;
|
||||
public int $minNumber = 10;
|
||||
|
||||
/**
|
||||
* @var bool
|
||||
* enable database cache
|
||||
*/
|
||||
public bool $enableCache = false;
|
||||
public string $cacheDriver = 'redis';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
*
|
||||
* @example [
|
||||
* 'cds' => 'mysql:dbname=dbname;host=127.0.0.1',
|
||||
* 'username' => 'root',
|
||||
* 'password' => 'root'
|
||||
* ]
|
||||
*/
|
||||
public array $slaveConfig = [];
|
||||
|
||||
private ?Schema $_schema = null;
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
Event::on(Event::SYSTEM_RESOURCE_CLEAN, [$this, 'disconnect']);
|
||||
Event::on(Event::SYSTEM_RESOURCE_RELEASES, [$this, 'clear_connection']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function enablingTransactions()
|
||||
{
|
||||
if (!Db::transactionsActive()) {
|
||||
return;
|
||||
}
|
||||
$this->beginTransaction();
|
||||
|
||||
Event::on(Connection::TRANSACTION_COMMIT, [$this, 'commit'], false, true);
|
||||
Event::on(Connection::TRANSACTION_ROLLBACK, [$this, 'rollback'], false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $sql
|
||||
* @return PDO
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getConnect($sql = NULL): PDO
|
||||
{
|
||||
return $this->getPdo($sql);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function fill()
|
||||
{
|
||||
$connections = $this->connections();
|
||||
$pool = Config::get('databases.pool.max', 10);
|
||||
|
||||
$connections->initConnections('Mysql:' . $this->cds, true, $pool);
|
||||
if (!empty($this->slaveConfig) && $this->cds != $this->slaveConfig['cds']) {
|
||||
$connections->initConnections('Mysql:' . $this->slaveConfig['cds'], false, $pool);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $sql
|
||||
* @return PDO
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getPdo($sql): PDO
|
||||
{
|
||||
if ($this->isWrite($sql)) {
|
||||
return $this->masterInstance();
|
||||
} else {
|
||||
return $this->slaveInstance();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @throws ReflectionException
|
||||
* @throws NotFindClassException
|
||||
*/
|
||||
public function getSchema(): Schema
|
||||
{
|
||||
if ($this->_schema === null) {
|
||||
$this->_schema = Snowflake::createObject([
|
||||
'class' => Schema::class,
|
||||
'db' => $this
|
||||
]);
|
||||
}
|
||||
return $this->_schema;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sql
|
||||
* @return bool
|
||||
*/
|
||||
#[Pure] public function isWrite($sql): bool
|
||||
{
|
||||
if (empty($sql)) return false;
|
||||
if (str_starts_with(strtolower($sql), 'select')) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getCacheDriver(): mixed
|
||||
{
|
||||
if (!$this->enableCache) {
|
||||
return null;
|
||||
}
|
||||
return Snowflake::app()->get($this->cacheDriver);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PDO
|
||||
* @throws Exception
|
||||
*/
|
||||
public function masterInstance(): PDO
|
||||
{
|
||||
return $this->connections()->get([
|
||||
'cds' => $this->cds,
|
||||
'username' => $this->username,
|
||||
'password' => $this->password,
|
||||
'database' => $this->database
|
||||
], true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return PDO
|
||||
* @throws Exception
|
||||
*/
|
||||
public function slaveInstance(): PDO
|
||||
{
|
||||
if (empty($this->slaveConfig) || Db::transactionsActive()) {
|
||||
return $this->masterInstance();
|
||||
}
|
||||
if ($this->slaveConfig['cds'] == $this->cds) {
|
||||
return $this->masterInstance();
|
||||
}
|
||||
return $this->connections()->get($this->slaveConfig, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return \Snowflake\Pool\Connection
|
||||
* @throws Exception
|
||||
*/
|
||||
private function connections(): \Snowflake\Pool\Connection
|
||||
{
|
||||
return Snowflake::app()->getMysqlFromPool();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function beginTransaction(): static
|
||||
{
|
||||
$this->connections()->beginTransaction($this->cds);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this|bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function inTransaction(): bool|static
|
||||
{
|
||||
return $this->connections()->inTransaction($this->cds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* 事务回滚
|
||||
*/
|
||||
public function rollback()
|
||||
{
|
||||
$this->connections()->rollback($this->cds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
* 事务提交
|
||||
*/
|
||||
public function commit()
|
||||
{
|
||||
$this->connections()->commit($this->cds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $sql
|
||||
* @return PDO
|
||||
* @throws Exception
|
||||
*/
|
||||
public function refresh($sql): PDO
|
||||
{
|
||||
if ($this->isWrite($sql)) {
|
||||
$instance = $this->masterInstance();
|
||||
} else {
|
||||
$instance = $this->slaveInstance();
|
||||
}
|
||||
return $instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $sql
|
||||
* @param string $dbname
|
||||
* @param array $attributes
|
||||
* @return Command
|
||||
* @throws Exception
|
||||
*/
|
||||
public function createCommand($sql = null, string $dbname = '', array $attributes = []): Command
|
||||
{
|
||||
$command = new Command(['db' => $this, 'sql' => $sql]);
|
||||
return $command->bindValues($attributes);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* 回收链接
|
||||
* @throws
|
||||
*/
|
||||
public function release()
|
||||
{
|
||||
$connections = $this->connections();
|
||||
|
||||
$connections->release($this->cds, true);
|
||||
$connections->release($this->slaveConfig['cds'], false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function recovery()
|
||||
{
|
||||
$connections = $this->connections();
|
||||
|
||||
$connections->release($this->cds, true);
|
||||
$connections->release($this->slaveConfig['cds'], false);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* 回收链接
|
||||
* @throws
|
||||
*/
|
||||
public function clear_connection()
|
||||
{
|
||||
$connections = $this->connections();
|
||||
|
||||
$connections->release($this->cds, true);
|
||||
$connections->release($this->slaveConfig['cds'], false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function disconnect()
|
||||
{
|
||||
$connections = $this->connections();
|
||||
$connections->disconnect($this->cds, true);
|
||||
$connections->disconnect($this->slaveConfig['cds'], false);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
use Annotation\IAnnotation;
|
||||
use Exception;
|
||||
use ReflectionException;
|
||||
use Snowflake\Abstracts\Providers;
|
||||
use Snowflake\Application;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Exception\ComponentException;
|
||||
use Snowflake\Exception\ConfigException;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
use Snowflake\Exception\NotFindPropertyException;
|
||||
use Snowflake\Snowflake;
|
||||
use Snowflake\Abstracts\Config;
|
||||
|
||||
/**
|
||||
* Class DatabasesProviders
|
||||
* @package Database
|
||||
*/
|
||||
class DatabasesProviders extends Providers
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Application $application
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onImport(Application $application)
|
||||
{
|
||||
$application->set('db', $this);
|
||||
|
||||
Event::on(Event::SERVER_TASK_START, [$this, 'createPool']);
|
||||
Event::on(Event::SERVER_WORKER_START, [$this, 'createPool']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return Connection
|
||||
* @throws ConfigException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get($name): Connection
|
||||
{
|
||||
$application = Snowflake::app();
|
||||
if ($application->has('databases.' . $name)) {
|
||||
return $application->get('databases.' . $name);
|
||||
}
|
||||
$config = $this->getConfig($name);
|
||||
|
||||
$max = Config::get('databases.pool.max', 30);
|
||||
return $application->set('databases.' . $name, [
|
||||
'class' => Connection::class,
|
||||
'id' => $config['id'],
|
||||
'cds' => $config['cds'],
|
||||
'username' => $config['username'],
|
||||
'password' => $config['password'],
|
||||
'tablePrefix' => $config['tablePrefix'],
|
||||
'maxNumber' => $max,
|
||||
'database' => $config['database'],
|
||||
'charset' => $config['charset'] ?? 'utf8mb4',
|
||||
'slaveConfig' => $config['slaveConfig']
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws ConfigException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function createPool()
|
||||
{
|
||||
$databases = Config::get('databases.connections', []);
|
||||
if (empty($databases)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$max = Config::get('databases.pool', ['max' => 10, 'min' => 10]);
|
||||
|
||||
$application = Snowflake::app();
|
||||
foreach ($databases as $name => $database) {
|
||||
/** @var Connection $connection */
|
||||
$connection = $application->set('databases.' . $name, [
|
||||
'class' => Connection::class,
|
||||
'id' => $database['id'],
|
||||
'cds' => $database['cds'],
|
||||
'username' => $database['username'],
|
||||
'password' => $database['password'],
|
||||
'tablePrefix' => $database['tablePrefix'],
|
||||
'database' => $database['database'],
|
||||
'maxNumber' => $max['max'],
|
||||
'minNumber' => $max['min'],
|
||||
'charset' => $database['charset'] ?? 'utf8mb4',
|
||||
'slaveConfig' => $database['slaveConfig']
|
||||
]);
|
||||
$connection->fill();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
* @throws ConfigException
|
||||
*/
|
||||
public function getConfig($name): mixed
|
||||
{
|
||||
return Config::get('databases.connections.' . $name, null, true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
-349
@@ -1,349 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/4 0004
|
||||
* Time: 15:40
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database;
|
||||
|
||||
use Database\Traits\QueryTrait;
|
||||
use Exception;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Db
|
||||
* @package Database
|
||||
*/
|
||||
class Db implements ISqlBuilder
|
||||
{
|
||||
use QueryTrait;
|
||||
|
||||
|
||||
private static bool $_inTransaction = false;
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public static function transactionsActive(): bool
|
||||
{
|
||||
return static::$_inTransaction === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function beginTransaction()
|
||||
{
|
||||
static::$_inTransaction = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function commit()
|
||||
{
|
||||
if (!static::transactionsActive()) {
|
||||
return;
|
||||
}
|
||||
Event::trigger(Connection::TRANSACTION_COMMIT);
|
||||
Event::offName(Connection::TRANSACTION_COMMIT);
|
||||
static::$_inTransaction = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function rollback()
|
||||
{
|
||||
if (!static::transactionsActive()) {
|
||||
return;
|
||||
}
|
||||
Event::trigger(Connection::TRANSACTION_ROLLBACK);
|
||||
Event::offName(Connection::TRANSACTION_ROLLBACK);
|
||||
static::$_inTransaction = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
*
|
||||
* @return static
|
||||
*/
|
||||
public static function table($table): Db|static
|
||||
{
|
||||
$db = new Db();
|
||||
$db->from($table);
|
||||
return $db;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param string $alias
|
||||
* @return string
|
||||
*/
|
||||
public static function any_value(string $column, string $alias = ''): string
|
||||
{
|
||||
if (empty($alias)) {
|
||||
$alias = $column . '_any_value';
|
||||
}
|
||||
return 'ANY_VALUE(' . $column . ') as ' . $alias;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @return string
|
||||
*/
|
||||
public static function increment(string $column): string
|
||||
{
|
||||
return '+ ' . $column;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @return string
|
||||
*/
|
||||
public static function decrement(string $column): string
|
||||
{
|
||||
return '- ' . $column;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Connection|null $db
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get(Connection $db = NULL): mixed
|
||||
{
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::app()->get('db');
|
||||
}
|
||||
return $db->createCommand(SqlBuilder::builder($this)->one())
|
||||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @return string
|
||||
*/
|
||||
public static function raw($column): string
|
||||
{
|
||||
return '`' . $column . '`';
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Connection|null $db
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function find(Connection $db = NULL): mixed
|
||||
{
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::app()->get('db');
|
||||
}
|
||||
return $db->createCommand(SqlBuilder::builder($this)->all())
|
||||
->one();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Connection|NULL $db
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function count(Connection $db = NULL): bool|int
|
||||
{
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::app()->get('db');
|
||||
}
|
||||
return $db->createCommand(SqlBuilder::builder($this)->count())
|
||||
->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Connection|NULL $db
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function exists(Connection $db = NULL): bool|int
|
||||
{
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::app()->get('db');
|
||||
}
|
||||
return $db->createCommand(SqlBuilder::builder($this)->one())
|
||||
->fetchColumn();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sql
|
||||
* @param array $attributes
|
||||
* @param Connection|null $db
|
||||
* @return array|bool|int|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function findAllBySql(string $sql, array $attributes = [], Connection $db = NULL): int|bool|array|string|null
|
||||
{
|
||||
return $db->createCommand($sql, $db?->database, $attributes)->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sql
|
||||
* @param array $attributes
|
||||
* @param Connection|NULL $db
|
||||
* @return string|array|bool|int|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function findBySql(string $sql, array $attributes = [], Connection $db = NULL): string|array|bool|int|null
|
||||
{
|
||||
return $db->createCommand($sql, $db?->database, $attributes)->one();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $field
|
||||
* @return array|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function values(string $field): ?array
|
||||
{
|
||||
$data = $this->get();
|
||||
if (empty($data) || empty($field)) {
|
||||
return NULL;
|
||||
}
|
||||
$first = current($data);
|
||||
if (!isset($first[$field])) {
|
||||
return NULL;
|
||||
}
|
||||
return array_column($data, $field);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function value($field): mixed
|
||||
{
|
||||
$data = $this->find();
|
||||
if (!empty($field) && isset($data[$field])) {
|
||||
return $data[$field];
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $db
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public function delete($db = null): bool|int
|
||||
{
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::app()->get('db');
|
||||
}
|
||||
|
||||
$query = $db->getBuild()->builder($this);
|
||||
|
||||
return $db->createCommand($query)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @param null $db
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function drop($table, $db = null): bool|int
|
||||
{
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::app()->get('db');
|
||||
}
|
||||
return $db->createCommand('DROP TABLE `' . $db->database . '`.' . $table)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @param null $db
|
||||
* @return bool|int
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function truncate($table, $db = null): bool|int
|
||||
{
|
||||
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::app()->get('db');
|
||||
}
|
||||
|
||||
return $db->createCommand('TRUNCATE `' . $db->database . '`.' . $table)->exec();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @param Connection|NULL $db
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function showCreateSql($table, Connection $db = NULL): mixed
|
||||
{
|
||||
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::app()->get('db');
|
||||
}
|
||||
|
||||
|
||||
if (empty($table)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $db->createCommand('SHOW CREATE TABLE `' . $db->database . '`.' . $table)->one();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @param Connection|NULL $db
|
||||
* @return bool|int|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function desc($table, Connection $db = NULL): bool|int|null
|
||||
{
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::app()->get('db');
|
||||
}
|
||||
|
||||
if (empty($table)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $db->createCommand('SHOW FULL FIELDS FROM `' . $db->database . '`.' . $table)->all();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $table
|
||||
* @param Connection|NULL $db
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function show(string $table, Connection $db = NULL): mixed
|
||||
{
|
||||
if (empty($table)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (empty($db)) {
|
||||
$db = Snowflake::app()->get('db');
|
||||
}
|
||||
|
||||
$table = [' const TABLE = \'select * from %s where REFERENCED_TABLE_NAME=%s\';'];
|
||||
|
||||
return $db->createCommand((new Query())
|
||||
->select('*')
|
||||
->from('INFORMATION_SCHEMA.KEY_COLUMN_USAGE')
|
||||
->where(['REFERENCED_TABLE_NAME' => $table])
|
||||
->getSql())->one();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database;
|
||||
|
||||
use Exception;
|
||||
use Database\Traits\HasBase;
|
||||
|
||||
/**
|
||||
* Class HasCount
|
||||
* @package Database
|
||||
*/
|
||||
class HasCount extends HasBase
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $arguments
|
||||
* @return ActiveQuery
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __call($name, $arguments): mixed
|
||||
{
|
||||
if (method_exists($this, $name)) {
|
||||
return call_user_func([$this, $name], ...$arguments);
|
||||
}
|
||||
return $this->_relation->getQuery($this->model::className())->$name(...$arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null|ActiveRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get(): array|ActiveRecord|null
|
||||
{
|
||||
return $this->_relation->count($this->model::className(), $this->value);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/4 0004
|
||||
* Time: 13:58
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
namespace Database;
|
||||
|
||||
use Exception;
|
||||
use Database\Traits\HasBase;
|
||||
|
||||
/**
|
||||
* Class HasMany
|
||||
* @package Database
|
||||
*
|
||||
* @method with($name)
|
||||
*/
|
||||
class HasMany extends HasBase
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $arguments
|
||||
* @return ActiveQuery
|
||||
*/
|
||||
public function __call($name, $arguments): mixed
|
||||
{
|
||||
if (method_exists($this, $name)) {
|
||||
return call_user_func([$this, $name], ...$arguments);
|
||||
}
|
||||
return $this->_relation->getQuery($this->model::className())->$name(...$arguments);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null|ActiveRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get(): array|ActiveRecord|null
|
||||
{
|
||||
return $this->_relation->get($this->model::className(), $this->value);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/4 0004
|
||||
* Time: 13:47
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database;
|
||||
|
||||
use Exception;
|
||||
use Database\Traits\HasBase;
|
||||
|
||||
/**
|
||||
* Class HasOne
|
||||
* @package Database
|
||||
* @internal Query
|
||||
*/
|
||||
class HasOne extends HasBase
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $arguments
|
||||
* @return ActiveQuery
|
||||
*/
|
||||
public function __call($name, $arguments): mixed
|
||||
{
|
||||
if (method_exists($this, $name)) {
|
||||
return call_user_func([$this, $name], ...$arguments);
|
||||
}
|
||||
$this->_relation->getQuery($this->model::className())->$name(...$arguments);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null|ActiveRecord
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get(): array|ActiveRecord|null
|
||||
{
|
||||
return $this->_relation->first($this->model::className(), $this->value);
|
||||
}
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/3/30 0030
|
||||
* Time: 14:39
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
namespace Database;
|
||||
|
||||
|
||||
/**
|
||||
* Interface IOrm
|
||||
* @package Database
|
||||
*/
|
||||
interface IOrm
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $param
|
||||
* @param null $db
|
||||
* @return ActiveRecord
|
||||
*/
|
||||
public static function findOne($param, $db = NULL): mixed;
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public static function className(): string;
|
||||
|
||||
|
||||
/**
|
||||
* @return ActiveQuery
|
||||
* return a sql queryBuilder
|
||||
*/
|
||||
public static function find(): ActiveQuery;
|
||||
|
||||
|
||||
/**
|
||||
* @param $dbName
|
||||
* @return Connection
|
||||
*/
|
||||
public static function setDatabaseConnect($dbName): Connection;
|
||||
|
||||
// public static function deleteAll($condition, $attributes);
|
||||
|
||||
// public static function updateAll($condition, $attributes);
|
||||
|
||||
}
|
||||
@@ -1,10 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
interface ISqlBuilder
|
||||
{
|
||||
|
||||
}
|
||||
@@ -1,406 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: admin
|
||||
* Date: 2019-03-18
|
||||
* Time: 17:22
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Mysql;
|
||||
|
||||
|
||||
use Database\Connection;
|
||||
use Database\SqlBuilder;
|
||||
use Exception;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Core\Json;
|
||||
|
||||
/**
|
||||
* Class Columns
|
||||
* @package Database\Mysql
|
||||
*/
|
||||
class Columns extends Component
|
||||
{
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* field types
|
||||
*/
|
||||
private array $columns = [];
|
||||
|
||||
/**
|
||||
* @var Connection
|
||||
* Mysql client
|
||||
*/
|
||||
public Connection $db;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
* tableName
|
||||
*/
|
||||
public string $table = '';
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* field primary key
|
||||
*/
|
||||
private array $_primary = [];
|
||||
|
||||
/**
|
||||
* @var array
|
||||
* by mysql field auto_increment
|
||||
*/
|
||||
private array $_auto_increment = [];
|
||||
|
||||
|
||||
private array $_fields = [];
|
||||
|
||||
/**
|
||||
* @param string $table
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function table(string $table): static
|
||||
{
|
||||
$this->structure($this->table = $table);
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getTable(): string
|
||||
{
|
||||
return $this->table;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $val
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function fieldFormat($key, $val): mixed
|
||||
{
|
||||
return $this->encode($val, $this->get_fields($key));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return array
|
||||
* @throws
|
||||
*/
|
||||
public function populate($data): array
|
||||
{
|
||||
$column = $this->get_fields();
|
||||
foreach ($data as $key => $val) {
|
||||
if (!isset($column[$key])) {
|
||||
continue;
|
||||
}
|
||||
$data[$key] = $this->decode($val, $column[$key]);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $val
|
||||
* @param null $format
|
||||
* @return mixed
|
||||
*/
|
||||
public function decode($val, $format = null): mixed
|
||||
{
|
||||
if (empty($format) || $val === null) {
|
||||
return $val;
|
||||
}
|
||||
$format = strtolower($format);
|
||||
if ($this->isInt($format)) {
|
||||
return (int)$val;
|
||||
} else if ($this->isJson($format)) {
|
||||
return Json::decode($val, true);
|
||||
} else if ($this->isFloat($format)) {
|
||||
return (float)$val;
|
||||
} else {
|
||||
return stripslashes($val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param $value
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function _decode(string $name, $value): mixed
|
||||
{
|
||||
return $this->decode($value, $this->get_fields($name));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $val
|
||||
* @param null $format
|
||||
* @return float|bool|int|string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function encode($val, $format = null): float|bool|int|string
|
||||
{
|
||||
if (empty($format)) {
|
||||
return $val;
|
||||
}
|
||||
$format = strtolower($format);
|
||||
if ($this->isInt($format)) {
|
||||
return (int)$val;
|
||||
} else if ($this->isJson($format)) {
|
||||
return Json::encode($val);
|
||||
} else if ($this->isFloat($format)) {
|
||||
return (float)$val;
|
||||
} else {
|
||||
return addslashes($val);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $format
|
||||
* @return bool
|
||||
*/
|
||||
#[Pure] public function isInt($format): bool
|
||||
{
|
||||
return in_array($format, ['int', 'bigint', 'tinyint', 'smallint', 'mediumint']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $format
|
||||
* @return bool
|
||||
*/
|
||||
#[Pure] public function isFloat($format): bool
|
||||
{
|
||||
return in_array($format, ['float', 'double', 'decimal']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $format
|
||||
* @return bool
|
||||
*/
|
||||
#[Pure] public function isJson($format): bool
|
||||
{
|
||||
return in_array($format, ['json']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $format
|
||||
* @return bool
|
||||
*/
|
||||
#[Pure] public function isString($format): bool
|
||||
{
|
||||
return in_array($format, ['varchar', 'char', 'text', 'longtext', 'tinytext', 'mediumtext']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws
|
||||
*/
|
||||
public function format(): array
|
||||
{
|
||||
return $this->columns('Default', 'Field');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getFields(): array
|
||||
{
|
||||
if (empty($this->_fields)) {
|
||||
$this->structure($this->table);
|
||||
}
|
||||
return $this->_fields[$this->table];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
public function hasField(string $name): bool
|
||||
{
|
||||
return array_key_exists($name, $this->getFields());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getAutoIncrement(): int|string|null
|
||||
{
|
||||
return $this->_auto_increment[$this->table] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null|string
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getPrimaryKeys(): array|string|null
|
||||
{
|
||||
if (isset($this->_auto_increment[$this->table])) {
|
||||
return $this->_auto_increment[$this->table];
|
||||
}
|
||||
return $this->_primary[$this->table] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|null|string
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
#[Pure] public function getFirstPrimary(): array|string|null
|
||||
{
|
||||
if (isset($this->_auto_increment[$this->table])) {
|
||||
return $this->_auto_increment[$this->table];
|
||||
}
|
||||
if (isset($this->_primary[$this->table])) {
|
||||
return current($this->_primary[$this->table]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param null $index
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function columns($name, $index = null): array
|
||||
{
|
||||
if (empty($index)) {
|
||||
return array_column($this->getColumns(), $name);
|
||||
} else {
|
||||
return array_column($this->getColumns(), $name, $index);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|static
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getColumns(): array|static
|
||||
{
|
||||
return $this->structure($this->getTable());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @return array|Columns
|
||||
* @throws Exception
|
||||
*/
|
||||
private function structure($table): array|static
|
||||
{
|
||||
if (!isset($this->columns[$table]) || empty($this->columns[$table])) {
|
||||
$column = $this->db->createCommand(SqlBuilder::builder(null)->columns($table))->all();
|
||||
if (empty($column)) {
|
||||
throw new Exception("The table " . $table . " not exists.");
|
||||
}
|
||||
return $this->columns[$table] = $this->resolve($column, $table);
|
||||
}
|
||||
return $this->columns[$table];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param $table
|
||||
* @return array
|
||||
*/
|
||||
private function resolve(array $column, $table): array
|
||||
{
|
||||
foreach ($column as $key => $item) {
|
||||
$this->addPrimary($item, $table);
|
||||
$column[$key]['Type'] = $this->clean($item['Type']);
|
||||
}
|
||||
|
||||
$this->_fields[$table] = array_column($column, 'Default', 'Field');
|
||||
|
||||
return $column;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $item
|
||||
* @param $table
|
||||
*/
|
||||
private function addPrimary($item, $table)
|
||||
{
|
||||
if (!isset($this->_primary[$table])) {
|
||||
$this->_primary[$table] = [];
|
||||
}
|
||||
if ($item['Key'] === 'PRI') {
|
||||
$this->_primary[$table][] = $item['Field'];
|
||||
}
|
||||
$this->addIncrement($item, $table);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $item
|
||||
* @param $table
|
||||
*/
|
||||
private function addIncrement($item, $table)
|
||||
{
|
||||
if ($item['Extra'] !== 'auto_increment') {
|
||||
return;
|
||||
}
|
||||
$this->_auto_increment[$table] = $item['Field'];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $type
|
||||
* @return string
|
||||
*/
|
||||
public function clean($type): string
|
||||
{
|
||||
if (!str_contains($type, ')')) {
|
||||
return $type;
|
||||
}
|
||||
$replace = preg_replace('/\(\d+(,\d+)?\)(\s+\w+)*/', '', $type);
|
||||
if (str_contains($replace, ' ')) {
|
||||
$replace = explode(' ', $replace)[1];
|
||||
}
|
||||
return $replace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param null $field
|
||||
* @return array|string|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get_fields($field = null): array|string|null
|
||||
{
|
||||
$fields = $this->getAllField();
|
||||
if (empty($field)) {
|
||||
return $fields;
|
||||
}
|
||||
if (isset($fields[$field])) {
|
||||
return strtolower($fields[$field]);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getAllField(): array
|
||||
{
|
||||
return $this->columns('Type', 'Field');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
namespace Database\Mysql;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Database\Connection;
|
||||
|
||||
/**
|
||||
* Class Schema
|
||||
* @package Database\Mysql
|
||||
*/
|
||||
class Schema extends Component
|
||||
{
|
||||
|
||||
/** @var ?Connection */
|
||||
public ?Connection $db;
|
||||
|
||||
/** @var ?Columns $_column*/
|
||||
private ?Columns $_column = null;
|
||||
|
||||
|
||||
/**
|
||||
* @return Columns|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getColumns(): ?Columns
|
||||
{
|
||||
if ($this->_column === null) {
|
||||
$this->_column = new Columns(['db' => $this->db]);
|
||||
}
|
||||
|
||||
return $this->_column;
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Orm;
|
||||
|
||||
|
||||
use Database\Traits\Builder;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Trait Condition
|
||||
* @package Database\Orm
|
||||
*/
|
||||
trait Condition
|
||||
{
|
||||
|
||||
|
||||
use Builder;
|
||||
|
||||
/**
|
||||
* @param $query
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getWhere($query): string
|
||||
{
|
||||
return $this->where($query);
|
||||
}
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
use Closure;
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Component;
|
||||
|
||||
/**
|
||||
* Class Pagination
|
||||
* @package Database
|
||||
*/
|
||||
class Pagination extends Component
|
||||
{
|
||||
|
||||
/** @var ActiveQuery */
|
||||
private ActiveQuery $activeQuery;
|
||||
|
||||
/** @var int 从第几个开始查 */
|
||||
private int $_offset = 0;
|
||||
|
||||
/** @var int 每页数量 */
|
||||
private int $_limit = 100;
|
||||
|
||||
/** @var int 最大查询数量 */
|
||||
private int $_max = 0;
|
||||
|
||||
/** @var int 当前已查询数量 */
|
||||
private int $_length = 0;
|
||||
|
||||
/** @var Closure */
|
||||
private Closure $_callback;
|
||||
|
||||
|
||||
/**
|
||||
* PaginationIteration constructor.
|
||||
* @param ActiveQuery $activeQuery
|
||||
* @param array $config
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct(ActiveQuery $activeQuery, array $config = [])
|
||||
{
|
||||
parent::__construct($config);
|
||||
$this->activeQuery = $activeQuery;
|
||||
}
|
||||
|
||||
|
||||
public function clean()
|
||||
{
|
||||
unset($this->activeQuery, $this->_callback, $this->_group);
|
||||
$this->_offset = 0;
|
||||
$this->_limit = 100;
|
||||
$this->_max = 0;
|
||||
$this->_length = 0;;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* recover class by clone
|
||||
*/
|
||||
public function __clone()
|
||||
{
|
||||
$this->clean();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array|Closure $callback
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setCallback(array|Closure $callback)
|
||||
{
|
||||
if (!is_callable($callback, true)) {
|
||||
throw new Exception('非法回调函数~');
|
||||
}
|
||||
$this->_callback = $callback;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $number
|
||||
* @return Pagination
|
||||
*/
|
||||
public function setOffset(int $number): static
|
||||
{
|
||||
if ($number < 0) {
|
||||
$number = 0;
|
||||
}
|
||||
$this->_offset = $number;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $number
|
||||
* @return Pagination
|
||||
*/
|
||||
public function setLimit(int $number): static
|
||||
{
|
||||
if ($number < 1) {
|
||||
$number = 100;
|
||||
} else if ($number > 5000) {
|
||||
$number = 5000;
|
||||
}
|
||||
$this->_limit = $number;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $number
|
||||
* @return Pagination
|
||||
*/
|
||||
public function setMax(int $number): static
|
||||
{
|
||||
if ($number < 0) {
|
||||
return $this;
|
||||
}
|
||||
$this->_max = $number;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $param
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function plunk($param = [])
|
||||
{
|
||||
$this->loop($param);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 轮训
|
||||
* @param $param
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function loop($param): array
|
||||
{
|
||||
if ($this->_max > 0 && $this->_length >= $this->_max) {
|
||||
return $this->output();
|
||||
}
|
||||
[$length, $data] = $this->get();
|
||||
|
||||
$this->executed($data, $param);
|
||||
|
||||
unset($data);
|
||||
if ($length < $this->_limit) {
|
||||
return $this->output();
|
||||
}
|
||||
return $this->loop($param);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function output(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param $param
|
||||
* @throws Exception
|
||||
*/
|
||||
private function executed($data, $param): void
|
||||
{
|
||||
try {
|
||||
call_user_func($this->_callback, $data, $param);
|
||||
} catch (\Throwable $exception) {
|
||||
$this->addError($exception, 'throwable');
|
||||
} finally {
|
||||
logger()->insert();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array|Collection
|
||||
*/
|
||||
private function get(): Collection|array
|
||||
{
|
||||
if ($this->_max > 0 && $this->_length + $this->_limit > $this->_max) {
|
||||
$this->_limit = $this->_length + $this->_limit - $this->_max;
|
||||
}
|
||||
$data = $this->activeQuery->limit($this->_offset, $this->_limit)->get();
|
||||
$this->_offset += $this->_limit;
|
||||
$this->_length += $data->size();
|
||||
return [$data->size(), $data];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/6/27 0027
|
||||
* Time: 17:49
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
use Database\Traits\QueryTrait;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class Query
|
||||
* @package Database
|
||||
*/
|
||||
class Query implements ISqlBuilder
|
||||
{
|
||||
|
||||
use QueryTrait;
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getSql(): string
|
||||
{
|
||||
return SqlBuilder::builder($this)->get();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getCondition(): string
|
||||
{
|
||||
return SqlBuilder::builder($this)->getCondition();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Component;
|
||||
|
||||
/**
|
||||
* Class Relation
|
||||
* @package Snowflake\db
|
||||
*/
|
||||
class Relation extends Component
|
||||
{
|
||||
|
||||
private array $_relations = [];
|
||||
|
||||
/** @var ActiveQuery[] $_query */
|
||||
private array $_query = [];
|
||||
|
||||
/**
|
||||
* @param string $identification
|
||||
* @param ActiveQuery $query
|
||||
* @return $this
|
||||
*/
|
||||
public function bindIdentification(string $identification, ActiveQuery $query): static
|
||||
{
|
||||
$this->_query[$identification] = $query;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return ActiveQuery|null
|
||||
*/
|
||||
public function getQuery(string $name): ?ActiveQuery
|
||||
{
|
||||
return $this->_query[$name] ?? null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $identification
|
||||
* @param $localValue
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function first(string $identification, $localValue): mixed
|
||||
{
|
||||
$_identification = $identification . '_first_' . $localValue;
|
||||
if (isset($this->_relations[$_identification]) && $this->_relations[$_identification] !== null) {
|
||||
return $this->_relations[$_identification];
|
||||
}
|
||||
|
||||
$activeModel = $this->_query[$identification]->first();
|
||||
if (empty($activeModel)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->_relations[$_identification] = $activeModel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $identification
|
||||
* @param $localValue
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function count(string $identification, $localValue): mixed
|
||||
{
|
||||
$_identification = $identification . '_count_' . $localValue;
|
||||
if (isset($this->_relations[$_identification]) && $this->_relations[$_identification] !== null) {
|
||||
return $this->_relations[$_identification];
|
||||
}
|
||||
|
||||
$activeModel = $this->_query[$identification]->count();
|
||||
if (empty($activeModel)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->_relations[$_identification] = $activeModel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $identification
|
||||
* @param $localValue
|
||||
* @return mixed
|
||||
*/
|
||||
public function get(string $identification, $localValue): mixed
|
||||
{
|
||||
if (is_array($localValue)) {
|
||||
$_identification = $identification . '_get_' . implode('_', $localValue);
|
||||
} else {
|
||||
$_identification = $identification . '_get_' . $localValue;
|
||||
}
|
||||
if (isset($this->_relations[$_identification]) && $this->_relations[$_identification] !== null) {
|
||||
return $this->_relations[$_identification];
|
||||
}
|
||||
|
||||
$activeModel = $this->_query[$identification]->get();
|
||||
if (empty($activeModel)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->_relations[$_identification] = $activeModel;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,358 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database;
|
||||
|
||||
|
||||
use Database\Traits\Builder;
|
||||
use Exception;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use Snowflake\Abstracts\Component;
|
||||
|
||||
|
||||
/**
|
||||
* Class SqlBuilder
|
||||
* @package Database
|
||||
*/
|
||||
class SqlBuilder extends Component
|
||||
{
|
||||
|
||||
use Builder;
|
||||
|
||||
|
||||
public ActiveQuery|Query|null $query;
|
||||
|
||||
|
||||
/**
|
||||
* @param $query
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function builder(ISqlBuilder|null $query): static
|
||||
{
|
||||
return new static(['query' => $query]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getCondition(): string
|
||||
{
|
||||
return $this->conditionToString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $attributes
|
||||
* @return bool|array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function update(array $attributes): bool|array
|
||||
{
|
||||
[$string, $array] = $this->builderParams($attributes);
|
||||
|
||||
return $this->__updateBuilder($string, $array);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $attributes
|
||||
* @param string $opera
|
||||
* @return bool|array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function mathematics(array $attributes, string $opera = '+'): bool|array
|
||||
{
|
||||
$string = [];
|
||||
foreach ($attributes as $attribute => $value) {
|
||||
$string[] = $attribute . '=' . $attribute . $opera . $value;
|
||||
}
|
||||
return $this->__updateBuilder($string, []);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $string
|
||||
* @param array $params
|
||||
* @return array|bool
|
||||
* @throws Exception
|
||||
*/
|
||||
private function __updateBuilder(array $string, array $params): array|bool
|
||||
{
|
||||
if (empty($string)) {
|
||||
return $this->addError('None data update.');
|
||||
}
|
||||
|
||||
$condition = $this->conditionToString();
|
||||
if (!empty($condition)) {
|
||||
$condition = ' WHERE ' . $condition;
|
||||
}
|
||||
|
||||
$update = 'UPDATE ' . $this->tableName() . ' SET ' . implode(',', $string) . $condition;
|
||||
$update .= $this->builderLimit($this->query, false);
|
||||
|
||||
return [$update, $params];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $attributes
|
||||
* @param false $isBatch
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function insert(array $attributes, bool $isBatch = false): array
|
||||
{
|
||||
$update = sprintf('INSERT INTO %s', $this->tableName());
|
||||
if ($isBatch === false) {
|
||||
$attributes = [$attributes];
|
||||
}
|
||||
$update .= '(' . implode(',', $this->getFields($attributes)) . ') VALUES ';
|
||||
|
||||
$order = 0;
|
||||
$keys = $params = [];
|
||||
foreach ($attributes as $attribute) {
|
||||
[$_keys, $params] = $this->builderParams($attribute, true, $params, $order);
|
||||
|
||||
$keys[] = implode(',', $_keys);
|
||||
$order++;
|
||||
}
|
||||
return [$update . '(' . implode('),(', $keys) . ')', $params];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function delete(): string
|
||||
{
|
||||
$delete = sprintf('DELETE FROM %s ', $this->query->modelClass::getTable());
|
||||
|
||||
$this->query->from = null;
|
||||
|
||||
return $delete . ' WHERE ' . $this->_prefix(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $attributes
|
||||
* @return array
|
||||
*/
|
||||
#[Pure] private function getFields($attributes): array
|
||||
{
|
||||
return array_keys(current($attributes));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $attributes
|
||||
* @param bool $isInsert
|
||||
* @param array $params
|
||||
* @param int $order
|
||||
* @return array[]
|
||||
* a=:b,
|
||||
*/
|
||||
#[Pure] private function builderParams(array $attributes, bool $isInsert = false, array $params = [], int $order = 0): array
|
||||
{
|
||||
$keys = [];
|
||||
foreach ($attributes as $key => $value) {
|
||||
if ($isInsert === true) {
|
||||
$keys[] = ':' . $key . $order;
|
||||
$params[$key . $order] = $value;
|
||||
} else {
|
||||
[$keys, $params] = $this->resolveParams($key, $value, $order, $params, $keys);
|
||||
}
|
||||
}
|
||||
return [$keys, $params];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param mixed $value
|
||||
* @param int $order
|
||||
* @param array $params
|
||||
* @param array $keys
|
||||
* @return array
|
||||
*/
|
||||
private function resolveParams(string $key, mixed $value, int $order, array $params, array $keys): array
|
||||
{
|
||||
if (
|
||||
str_starts_with($value, '+ ') ||
|
||||
str_starts_with($value, '- ')
|
||||
) {
|
||||
$keys[] = $key . '=' . $key . ' ' . $value;
|
||||
} else {
|
||||
$params[$key . $order] = $value;
|
||||
$keys[] = $key . '=:' . $key . $order;
|
||||
}
|
||||
return [$keys, $params];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function one(): string
|
||||
{
|
||||
$this->query->limit(0, 1);
|
||||
if (empty($this->query->from) && !empty($this->query->modelClass)) {
|
||||
$this->query->from($this->query->getTable());
|
||||
}
|
||||
return $this->_prefix(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function all(): string
|
||||
{
|
||||
if (empty($this->query->from) && !empty($this->query->modelClass)) {
|
||||
$this->query->from($this->query->getTable());
|
||||
}
|
||||
return $this->_prefix(true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function count(): string
|
||||
{
|
||||
if (empty($this->query->from) && !empty($this->query->modelClass)) {
|
||||
$this->query->from($this->query->getTable());
|
||||
}
|
||||
return $this->_prefix();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @return string
|
||||
*/
|
||||
public function columns($table): string
|
||||
{
|
||||
return 'SHOW FULL FIELDS FROM ' . $table;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param bool $hasOrder
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
private function _prefix(bool $hasOrder = false): string
|
||||
{
|
||||
$select = '';
|
||||
if (!empty($this->query->from)) {
|
||||
$select = $this->_selectPrefix();
|
||||
}
|
||||
$select = $this->_wherePrefix($select);
|
||||
if (!empty($this->query->attributes) && is_array($this->query->attributes)) {
|
||||
$select = strtr($select, $this->query->attributes);
|
||||
}
|
||||
|
||||
if (!empty($this->query->group)) {
|
||||
$select .= $this->builderGroup($this->query->group);
|
||||
}
|
||||
if ($hasOrder === true && !empty($this->query->order)) {
|
||||
$select .= $this->builderOrder($this->query->order);
|
||||
}
|
||||
return $select . $this->builderLimit($this->query);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $select
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
private function _wherePrefix($select): string
|
||||
{
|
||||
$condition = $this->conditionToString();
|
||||
if (empty($condition)) {
|
||||
return $select;
|
||||
} else if (empty($select)) {
|
||||
return $condition;
|
||||
}
|
||||
return sprintf('%s WHERE %s', $select, $condition);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
private function _selectPrefix(): string
|
||||
{
|
||||
$select = $this->builderSelect($this->query->select) . ' FROM ' . $this->tableName();
|
||||
if (!empty($this->query->alias)) {
|
||||
$select .= $this->builderAlias($this->query->alias);
|
||||
}
|
||||
if (!empty($this->query->join)) {
|
||||
$select .= $this->builderJoin($this->query->join);
|
||||
}
|
||||
return $select;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param false $isCount
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get(bool $isCount = false): string
|
||||
{
|
||||
if ($isCount === false) {
|
||||
return $this->all();
|
||||
}
|
||||
return $this->count();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function truncate(): string
|
||||
{
|
||||
return sprintf('TRUNCATE %s', $this->tableName());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
private function conditionToString(): string
|
||||
{
|
||||
return $this->where($this->query->where);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function tableName(): string
|
||||
{
|
||||
if ($this->query->from instanceof \Closure) {
|
||||
$this->query->from = sprintf('(%s)', $this->query->makeClosureFunction($this->query->from));
|
||||
}
|
||||
if ($this->query->from instanceof ActiveQuery) {
|
||||
$this->query->from = sprintf('%s', SqlBuilder::builder($this->query->from)->get($this->query->from));
|
||||
}
|
||||
if (empty($this->query->from)) {
|
||||
return $this->query->modelClass::getTable();
|
||||
}
|
||||
return $this->query->from;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,218 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Traits;
|
||||
|
||||
|
||||
use Database\ActiveQuery;
|
||||
use Database\Base\ConditionClassMap;
|
||||
use Database\Condition\HashCondition;
|
||||
use Database\Condition\OrCondition;
|
||||
use Database\Query;
|
||||
use Database\SqlBuilder;
|
||||
use Exception;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use ReflectionException;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
|
||||
/**
|
||||
* Trait Builder
|
||||
* @package Database\Traits
|
||||
*/
|
||||
trait Builder
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param $alias
|
||||
* @return string
|
||||
*/
|
||||
private function builderAlias($alias): string
|
||||
{
|
||||
return " AS " . $alias;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $table
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
private function builderFrom($table): string
|
||||
{
|
||||
if ($table instanceof ActiveQuery) {
|
||||
$table = '(' . $table->toSql() . ')';
|
||||
}
|
||||
return " FROM " . $table;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $join
|
||||
* @return string
|
||||
*/
|
||||
#[Pure] private function builderJoin($join): string
|
||||
{
|
||||
if (!empty($join)) {
|
||||
return ' ' . implode(' ', $join);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param null $select
|
||||
* @return string
|
||||
*/
|
||||
#[Pure] private function builderSelect($select = NULL): string
|
||||
{
|
||||
if (empty($select)) {
|
||||
return "SELECT *";
|
||||
}
|
||||
if (is_array($select)) {
|
||||
return "SELECT " . implode(',', $select);
|
||||
} else {
|
||||
return "SELECT " . $select;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $group
|
||||
* @return string
|
||||
*/
|
||||
private function builderGroup($group): string
|
||||
{
|
||||
if (empty($group)) {
|
||||
return '';
|
||||
}
|
||||
return ' GROUP BY ' . $group;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $order
|
||||
* @return string
|
||||
*/
|
||||
#[Pure] private function builderOrder($order): string
|
||||
{
|
||||
if (!empty($order)) {
|
||||
return ' ORDER BY ' . implode(',', $order);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ActiveQuery|Query $query
|
||||
* @param bool $hasLimit
|
||||
* @return string
|
||||
*/
|
||||
#[Pure] private function builderLimit(ActiveQuery|Query $query, bool $hasLimit = true): string
|
||||
{
|
||||
if (!is_numeric($query->limit) || $query->limit < 1) {
|
||||
return "";
|
||||
}
|
||||
if ($query->offset !== null && $hasLimit) {
|
||||
return ' LIMIT ' . $query->offset . ',' . $query->limit;
|
||||
}
|
||||
return ' LIMIT ' . $query->limit;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $where
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
private function where($where): string
|
||||
{
|
||||
$_tmp = [];
|
||||
if (empty($where)) return '';
|
||||
if (is_string($where)) return $where;
|
||||
foreach ($where as $key => $value) {
|
||||
$_value = $this->resolveCondition($key, $value, $_tmp);
|
||||
|
||||
if (empty($_value)) continue;
|
||||
$_tmp[] = $_value;
|
||||
}
|
||||
if (!empty($_tmp)) {
|
||||
return implode(' AND ', $_tmp);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
* @param $condition
|
||||
* @param $_tmp
|
||||
* @return string
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
private function resolveCondition($field, $condition, $_tmp): string
|
||||
{
|
||||
if (is_string($field)) {
|
||||
$_value = sprintf('%s = \'%s\'', $field, $condition);
|
||||
} else if (is_string($condition)) {
|
||||
$_value = $condition;
|
||||
} else {
|
||||
$_value = $this->_arrayMap($condition, $_tmp);
|
||||
}
|
||||
return $_value;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $condition
|
||||
* @param $array
|
||||
* @return string
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
* @throws ReflectionException
|
||||
*/
|
||||
private function _arrayMap($condition, $array): string
|
||||
{
|
||||
if (!isset($condition[0])) {
|
||||
return implode(' AND ', $this->_hashMap($condition));
|
||||
}
|
||||
$stroppier = strtoupper($condition[0]);
|
||||
if (str_contains($stroppier, 'OR')) {
|
||||
if (!is_string($condition[2])) {
|
||||
$condition[2] = $this->_hashMap($condition[2]);
|
||||
}
|
||||
$builder = Snowflake::createObject(['class' => OrCondition::class, 'value' => $condition[2], 'column' => $condition[1], 'oldParams' => $array]);
|
||||
} else if (isset(ConditionClassMap::$conditionMap[$stroppier])) {
|
||||
$defaultConfig = ConditionClassMap::$conditionMap[$stroppier];
|
||||
$create = array_merge($defaultConfig, ['column' => $condition[1], 'value' => $condition[2]]);
|
||||
$builder = Snowflake::createObject($create);
|
||||
} else {
|
||||
$builder = Snowflake::createObject(['class' => HashCondition::class, 'value' => $condition]);
|
||||
}
|
||||
|
||||
$array[] = $builder->builder();
|
||||
|
||||
return implode(' AND ', $array);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $condition
|
||||
* @return array
|
||||
*/
|
||||
private function _hashMap($condition): array
|
||||
{
|
||||
$_array = [];
|
||||
foreach ($condition as $key => $value) {
|
||||
$value = is_numeric($value) ? $value : '\'' . $value . '\'';
|
||||
if (!is_numeric($key)) {
|
||||
$_array[] = sprintf('%s = %s', $key, $value);
|
||||
} else {
|
||||
$_array[] = $value;
|
||||
}
|
||||
}
|
||||
return $_array;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/4/4 0004
|
||||
* Time: 15:47
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Traits;
|
||||
|
||||
use Database\ActiveRecord;
|
||||
use Database\Collection;
|
||||
use Database\IOrm;
|
||||
use Database\Relation;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class HasBase
|
||||
* @package Database
|
||||
*
|
||||
* @include Query
|
||||
*/
|
||||
abstract class HasBase
|
||||
{
|
||||
|
||||
/** @var ActiveRecord|Collection */
|
||||
protected Collection|ActiveRecord $data;
|
||||
|
||||
/**
|
||||
* @var IOrm|ActiveRecord
|
||||
*/
|
||||
protected mixed $model;
|
||||
|
||||
protected mixed $value = [];
|
||||
|
||||
|
||||
/** @var Relation $_relation */
|
||||
protected Relation $_relation;
|
||||
|
||||
/**
|
||||
* HasBase constructor.
|
||||
* @param IOrm $model
|
||||
* @param $primaryId
|
||||
* @param $value
|
||||
* @param Relation $relation
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct(mixed $model, $primaryId, $value, Relation $relation)
|
||||
{
|
||||
if (!class_exists($model)) {
|
||||
throw new Exception('Model must implement ' . ActiveRecord::class);
|
||||
}
|
||||
if (!in_array(IOrm::class, class_implements($model))) {
|
||||
throw new Exception('Model must implement ' . ActiveRecord::class);
|
||||
}
|
||||
if (is_array($value)) {
|
||||
if (empty($value)) $value = [];
|
||||
$_model = $model::find()->in($primaryId, $value);
|
||||
} else {
|
||||
$_model = $model::find()->where(['t1.' . $primaryId => $value]);
|
||||
}
|
||||
|
||||
$this->_relation = $relation->bindIdentification($model, $_model);
|
||||
|
||||
$this->model = $model;
|
||||
$this->value = $value;
|
||||
}
|
||||
|
||||
abstract public function get();
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name): mixed
|
||||
{
|
||||
if (empty($this->value)) {
|
||||
return null;
|
||||
}
|
||||
return $this->get();
|
||||
}
|
||||
}
|
||||
@@ -1,871 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/3/30 0030
|
||||
* Time: 14:56
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Database\Traits;
|
||||
|
||||
|
||||
use Closure;
|
||||
use Database\ActiveQuery;
|
||||
use Database\ActiveRecord;
|
||||
use Database\Condition\MathematicsCondition;
|
||||
use Database\Query;
|
||||
use Exception;
|
||||
use ReflectionException;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Trait QueryTrait
|
||||
* @package Database\Traits
|
||||
*/
|
||||
trait QueryTrait
|
||||
{
|
||||
public array $where = [];
|
||||
public array $select = [];
|
||||
public array $join = [];
|
||||
public array $order = [];
|
||||
public ?int $offset = NULL;
|
||||
public ?int $limit = NULL;
|
||||
public string $group = '';
|
||||
public string|Closure|ActiveQuery|null $from = '';
|
||||
public string $alias = 't1';
|
||||
public array $filter = [];
|
||||
|
||||
public bool $ifNotWhere = false;
|
||||
|
||||
/**
|
||||
* @var ActiveRecord|string|null
|
||||
*/
|
||||
public ActiveRecord|string|null $modelClass;
|
||||
|
||||
/**
|
||||
* clear
|
||||
*/
|
||||
public function clear()
|
||||
{
|
||||
$this->where = [];
|
||||
$this->select = [];
|
||||
$this->join = [];
|
||||
$this->order = [];
|
||||
$this->offset = NULL;
|
||||
$this->limit = NULL;
|
||||
$this->group = '';
|
||||
$this->from = '';
|
||||
$this->alias = 't1';
|
||||
$this->filter = [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param callable $callable
|
||||
* @return $this
|
||||
*/
|
||||
public function case(string $column, callable $callable): static
|
||||
{
|
||||
$caseWhen = new When($column, $this);
|
||||
|
||||
call_user_func($callable, $caseWhen);
|
||||
|
||||
$this->where[] = $caseWhen->end();
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $condition
|
||||
* @param $condition1
|
||||
* @param $condition2
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function if(string|array $condition, string|array|Closure $condition1, string|array|Closure $condition2): static
|
||||
{
|
||||
if (!is_string($condition)) {
|
||||
$condition = $this->makeClosureFunction($condition, true);
|
||||
}
|
||||
if (!is_string($condition1)) {
|
||||
$condition1 = $this->makeClosureFunction($condition1, true);
|
||||
}
|
||||
if (!is_string($condition2)) {
|
||||
$condition2 = $this->makeClosureFunction($condition2, true);
|
||||
}
|
||||
$this->where[] = 'IF(' . $condition . ', ' . $condition1 . ', ' . $condition2 . ')';
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $condition
|
||||
* @return string
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
private function conditionToString($condition): string
|
||||
{
|
||||
$newSql = $this->makeNewSqlGenerate();
|
||||
if ($condition instanceof Closure) {
|
||||
call_user_func($condition, $newSql);
|
||||
} else {
|
||||
$newSql->where($condition);
|
||||
}
|
||||
return $newSql->getCondition();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $bool
|
||||
* @return $this
|
||||
*/
|
||||
public function ifNotWhere($bool): static
|
||||
{
|
||||
$this->ifNotWhere = $bool;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getTable(): string
|
||||
{
|
||||
return $this->modelClass::getTable();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param string $value
|
||||
* @return $this
|
||||
*/
|
||||
public function locate(string $column, string $value): static
|
||||
{
|
||||
$this->where[] = 'LOCATE(' . $column . ',\'' . addslashes($value) . '\') > 0';
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @return $this
|
||||
*/
|
||||
public function isNull($column): static
|
||||
{
|
||||
$this->where[] = $column . ' IS NULL';
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @return $this
|
||||
*/
|
||||
public function isEmpty($column): static
|
||||
{
|
||||
$this->where[] = $column . ' = \'\'';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @return $this
|
||||
*/
|
||||
public function isNotEmpty($column): static
|
||||
{
|
||||
$this->where[] = $column . ' <> \'\'';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @return $this
|
||||
*/
|
||||
public function isNotNull($column): static
|
||||
{
|
||||
$this->where[] = $column . ' IS NOT NULL';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function filter($columns): static
|
||||
{
|
||||
if (!$columns) {
|
||||
return $this;
|
||||
}
|
||||
if (is_callable($columns, TRUE)) {
|
||||
return call_user_func($columns, $this);
|
||||
}
|
||||
if (is_string($columns)) {
|
||||
$columns = explode(',', $columns);
|
||||
}
|
||||
if (!is_array($columns)) {
|
||||
return $this;
|
||||
}
|
||||
$this->filter = $columns;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $alias
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* select * from tableName as t1
|
||||
*/
|
||||
public function alias($alias = 't1'): static
|
||||
{
|
||||
$this->alias = $alias;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|Closure $tableName
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function from(string|Closure $tableName): static
|
||||
{
|
||||
$this->from = $tableName;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $tableName
|
||||
* @param string $alias
|
||||
* @param null $on
|
||||
* @param array|null $param
|
||||
* @return $this
|
||||
* $query->join([$tableName, ['userId'=>'uuvOd']], $param)
|
||||
* $query->join([$tableName, ['userId'=>'uuvOd'], $param])
|
||||
* $query->join($tableName, ['userId'=>'uuvOd',$param])
|
||||
*/
|
||||
private function join(string $tableName, string $alias, $on = NULL, array $param = NULL): static
|
||||
{
|
||||
if (empty($on)) {
|
||||
return $this;
|
||||
}
|
||||
$join[] = $tableName . ' AS ' . $alias;
|
||||
$join[] = 'ON ' . $this->onCondition($alias, $on);
|
||||
if (empty($join)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->join[] = implode(' ', $join);
|
||||
if (!empty($param)) {
|
||||
$this->addParams($param);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $alias
|
||||
* @param $on
|
||||
* @return string
|
||||
*/
|
||||
private function onCondition($alias, $on): string
|
||||
{
|
||||
$array = [];
|
||||
foreach ($on as $key => $item) {
|
||||
if (!str_contains($item, '.')) {
|
||||
$this->addParam($key, $item);
|
||||
} else {
|
||||
$explode = explode('.', $item);
|
||||
if (isset($explode[1]) && ($explode[0] == $alias || $this->alias == $explode[0])) {
|
||||
$array[] = $key . '=' . $item;
|
||||
} else {
|
||||
$this->addParam($key, $item);
|
||||
}
|
||||
}
|
||||
}
|
||||
return implode(' AND ', $array);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tableName
|
||||
* @param $alias
|
||||
* @param $onCondition
|
||||
* @param null $param
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function leftJoin(string $tableName, string $alias, $onCondition, $param = NULL): static
|
||||
{
|
||||
if (class_exists($tableName)) {
|
||||
if (!in_array(ActiveRecord::class, class_implements($tableName))) {
|
||||
throw new Exception('Model must implement ' . $tableName);
|
||||
}
|
||||
$tableName = $tableName::getTable();
|
||||
}
|
||||
return $this->join(...["LEFT JOIN " . $tableName, $alias, $onCondition, $param]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tableName
|
||||
* @param $alias
|
||||
* @param $onCondition
|
||||
* @param null $param
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function rightJoin($tableName, $alias, $onCondition, $param = NULL): static
|
||||
{
|
||||
if (class_exists($tableName)) {
|
||||
if (!in_array(ActiveRecord::class, class_implements($tableName))) {
|
||||
throw new Exception('Model must implement ' . $tableName);
|
||||
}
|
||||
$tableName = $tableName::getTable();
|
||||
}
|
||||
return $this->join(...["RIGHT JOIN " . $tableName, $alias, $onCondition, $param]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $tableName
|
||||
* @param $alias
|
||||
* @param $onCondition
|
||||
* @param null $param
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function innerJoin($tableName, $alias, $onCondition, $param = NULL): static
|
||||
{
|
||||
if (class_exists($tableName)) {
|
||||
if (!in_array(ActiveRecord::class, class_implements($tableName))) {
|
||||
throw new Exception('Model must implement ' . $tableName);
|
||||
}
|
||||
$tableName = $tableName::getTable();
|
||||
}
|
||||
return $this->join(...["INNER JOIN " . $tableName, $alias, $onCondition, $param]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $array
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function toString($array): string
|
||||
{
|
||||
$tmp = [];
|
||||
if (!is_array($array)) {
|
||||
return $array;
|
||||
}
|
||||
foreach ($array as $key => $val) {
|
||||
if (is_array($val)) {
|
||||
$tmp[] = $this->toString($array);
|
||||
} else {
|
||||
$tmp[] = $key . '=:' . $key;
|
||||
$this->attributes[':' . $key] = $val;
|
||||
}
|
||||
}
|
||||
return implode(' AND ', $tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function sum($field): static
|
||||
{
|
||||
$this->select[] = 'SUM(' . $field . ') AS ' . $field;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $field
|
||||
* @return $this
|
||||
*/
|
||||
public function max($field): static
|
||||
{
|
||||
$this->select[] = 'MAX(' . $field . ') AS ' . $field;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $lngField
|
||||
* @param string $latField
|
||||
* @param int $lng1
|
||||
* @param int $lat1
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function distance(string $lngField, string $latField, int $lng1, int $lat1): static
|
||||
{
|
||||
$sql = "ROUND(6378.138 * 2 * ASIN(SQRT(POW(SIN(($lat1 * PI() / 180 - $lat1 * PI() / 180) / 2),2) + COS($lat1 * PI() / 180) * COS($latField * PI() / 180) * POW(SIN(($lng1 * PI() / 180 - $lngField * PI() / 180) / 2),2))) * 1000) AS distance";
|
||||
$this->select[] = $sql;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param string $sort
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
* [
|
||||
* 'addTime',
|
||||
* 'descTime desc'
|
||||
* ]
|
||||
*/
|
||||
public function orderBy($column, $sort = 'DESC'): static
|
||||
{
|
||||
if (empty($column)) {
|
||||
return $this;
|
||||
}
|
||||
if (is_string($column)) {
|
||||
return $this->addOrder(...func_get_args());
|
||||
}
|
||||
|
||||
foreach ($column as $key => $val) {
|
||||
$this->addOrder($val);
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $column
|
||||
* @param string $sort
|
||||
*
|
||||
* @return $this
|
||||
*
|
||||
*/
|
||||
private function addOrder($column, $sort = 'DESC'): static
|
||||
{
|
||||
$column = trim($column);
|
||||
|
||||
if (func_num_args() == 1 || str_contains($column, ' ')) {
|
||||
$this->order[] = $column;
|
||||
} else {
|
||||
$this->order[] = "$column $sort";
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string $column
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function select($column = '*'): static
|
||||
{
|
||||
if ($column == '*') {
|
||||
$this->select = $column;
|
||||
} else {
|
||||
if (!is_array($column)) {
|
||||
$column = explode(',', $column);
|
||||
}
|
||||
foreach ($column as $key => $val) {
|
||||
$this->select[] = $val;
|
||||
}
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function orderRand(): static
|
||||
{
|
||||
$this->order[] = 'RAND()';
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $conditionArray
|
||||
*
|
||||
* @return QueryTrait
|
||||
*/
|
||||
public function or(array $conditionArray = []): static
|
||||
{
|
||||
$this->where = ['or', $conditionArray];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $columns
|
||||
* @param string|int|bool|null $value
|
||||
*
|
||||
* @param string $opera
|
||||
* @return QueryTrait
|
||||
*/
|
||||
public function and(string $columns, string|int|null|bool $value = NULL, $opera = '='): static
|
||||
{
|
||||
if (!is_numeric($value) && !is_bool($value)) {
|
||||
$value = '\'' . $value . '\'';
|
||||
}
|
||||
$this->where[] = $columns . $opera . $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @param string $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function like($columns, string $value): static
|
||||
{
|
||||
if (empty($columns) || empty($value)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (is_array($columns)) {
|
||||
$columns = 'CONCAT(' . implode(',^,', $columns) . ')';
|
||||
}
|
||||
|
||||
$this->where[] = $columns . ' LIKE \'%' . addslashes($value) . '%\'';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @param string $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function lLike($columns, string $value): static
|
||||
{
|
||||
if (empty($columns) || empty($value)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (is_array($columns)) {
|
||||
$columns = 'CONCAT(' . implode(',^,', $columns) . ')';
|
||||
}
|
||||
|
||||
$this->where[] = $columns . ' LLike \'%' . addslashes($value) . '\'';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @param string $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function rLike($columns, string $value): static
|
||||
{
|
||||
if (empty($columns) || empty($value)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (is_array($columns)) {
|
||||
$columns = 'CONCAT(' . implode(',^,', $columns) . ')';
|
||||
}
|
||||
|
||||
$this->where[] = $columns . ' RLike \'' . addslashes($value) . '%\'';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @param string $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function notLike($columns, string $value): static
|
||||
{
|
||||
if (empty($columns) || empty($value)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (is_array($columns)) {
|
||||
$columns = 'CONCAT(' . implode(',^,', $columns) . ')';
|
||||
}
|
||||
|
||||
$this->where[] = $columns . ' NOT LIKE \'%' . addslashes($value) . '%\'';
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
* @see MathematicsCondition
|
||||
*/
|
||||
public function eq(string $column, int $value): static
|
||||
{
|
||||
$this->where[] = ['EQ', $column, $value];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
* @see MathematicsCondition
|
||||
*/
|
||||
public function neq(string $column, int $value): static
|
||||
{
|
||||
$this->where[] = ['NEQ', $column, $value];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
* @see MathematicsCondition
|
||||
*/
|
||||
public function gt(string $column, int $value): static
|
||||
{
|
||||
$this->where[] = ['GT', $column, $value];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
* @see MathematicsCondition
|
||||
*/
|
||||
public function egt(string $column, int $value): static
|
||||
{
|
||||
$this->where[] = ['EGT', $column, $value];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
* @see MathematicsCondition
|
||||
*/
|
||||
public function lt(string $column, int $value): static
|
||||
{
|
||||
$this->where[] = ['LT', $column, $value];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
* @see MathematicsCondition
|
||||
*/
|
||||
public function elt(string $column, int $value): static
|
||||
{
|
||||
$this->where[] = ['ELT', $column, $value];
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @param $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function in($columns, $value): static
|
||||
{
|
||||
if ($value instanceof Closure) {
|
||||
$value = $this->makeClosureFunction($value);
|
||||
}
|
||||
if (empty($value)) {
|
||||
$value = [-1];
|
||||
}
|
||||
$this->where[] = ['IN', $columns, $value];
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $value
|
||||
* @return ActiveQuery
|
||||
* @throws Exception
|
||||
*/
|
||||
public function makeNewQuery($value): ActiveQuery
|
||||
{
|
||||
$activeQuery = new ActiveQuery($this->modelClass);
|
||||
call_user_func($value, $activeQuery);
|
||||
if (empty($activeQuery->from)) {
|
||||
$activeQuery->from($activeQuery->modelClass::getTable());
|
||||
}
|
||||
return $activeQuery;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Query
|
||||
* @throws ReflectionException
|
||||
* @throws NotFindClassException
|
||||
*/
|
||||
public function makeNewSqlGenerate(): Query
|
||||
{
|
||||
return Snowflake::createObject(Query::class);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $columns
|
||||
* @param $value
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function notIn($columns, $value): static
|
||||
{
|
||||
if (empty($value) || !is_array($value)) {
|
||||
$value = [-1];
|
||||
}
|
||||
$this->where[] = ['NOT IN', $columns, $value];
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $start
|
||||
* @param int $end
|
||||
* @return $this
|
||||
*/
|
||||
public function between(string $column, int $start, int $end): static
|
||||
{
|
||||
if (empty($column) || empty($start) || empty($end)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->where[] = $column . ' BETWEEN ' . $start . ' AND ' . $end;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $column
|
||||
* @param int $start
|
||||
* @param int $end
|
||||
* @return $this
|
||||
*/
|
||||
public function notBetween(string $column, int $start, int $end): static
|
||||
{
|
||||
if (empty($column) || empty($start) || empty($end)) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
$this->where[] = $column . 'NOT BETWEEN' . $start . ' AND ' . $end;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $params
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function bindParams(array $params = []): static
|
||||
{
|
||||
if (empty($params)) {
|
||||
return $this;
|
||||
}
|
||||
$this->attributes = $params;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param callable|array|string $conditions
|
||||
* @return $this
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function where(callable|array|string $conditions): static
|
||||
{
|
||||
if ($conditions instanceof Closure) {
|
||||
$conditions = $this->makeClosureFunction($conditions);
|
||||
}
|
||||
$this->where[] = $conditions;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Closure|array $closure
|
||||
* @param bool $onlyWhere
|
||||
* @return string
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
public function makeClosureFunction(Closure|array $closure, $onlyWhere = false): string
|
||||
{
|
||||
$generate = $this->makeNewSqlGenerate();
|
||||
if ($closure instanceof Closure) {
|
||||
call_user_func($closure, $generate);
|
||||
} else {
|
||||
$generate->where($closure);
|
||||
}
|
||||
return $onlyWhere ? $generate->getCondition() : $generate->getSql();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $name
|
||||
* @param string|null $having
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function groupBy(string $name, string $having = NULL): static
|
||||
{
|
||||
$this->group = $name;
|
||||
if (empty($having)) {
|
||||
return $this;
|
||||
}
|
||||
$this->group .= ' HAVING ' . $having;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $offset
|
||||
* @param int $limit
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function limit(int $offset, int $limit = 20): static
|
||||
{
|
||||
$this->offset = $offset;
|
||||
$this->limit = $limit;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return $this
|
||||
*/
|
||||
public function oneLimit(): static
|
||||
{
|
||||
$this->limit = 1;
|
||||
return $this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace Database\Traits;
|
||||
|
||||
|
||||
use Database\ActiveQuery;
|
||||
use Database\Query;
|
||||
use Exception;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
|
||||
|
||||
/**
|
||||
* Class CaseWhen
|
||||
* @package Database\Traits
|
||||
*/
|
||||
class When
|
||||
{
|
||||
|
||||
public ActiveQuery|QueryTrait $query;
|
||||
|
||||
|
||||
private array $_condition = [];
|
||||
|
||||
private string $else = '';
|
||||
|
||||
|
||||
/**
|
||||
* CaseWhen constructor.
|
||||
* @param string $column
|
||||
* @param ActiveQuery|QueryTrait $activeQuery
|
||||
*/
|
||||
public function __construct(public string $column, public ActiveQuery|QueryTrait $activeQuery)
|
||||
{
|
||||
$this->_condition[] = 'CASE ' . $column;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array|string $condition
|
||||
* @param string $then
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function when(array|string $condition, string $then): static
|
||||
{
|
||||
$this->_condition[] = sprintf('WHEN %s THEN %s', $this->activeQuery->makeNewSqlGenerate()
|
||||
->where($condition)
|
||||
->getCondition(), $then);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $alias
|
||||
*/
|
||||
public function else(string $alias)
|
||||
{
|
||||
$this->else = $alias;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
#[Pure] public function end(): string
|
||||
{
|
||||
if (empty($this->_condition)) {
|
||||
return '';
|
||||
}
|
||||
$prefix = implode(' ', $this->_condition);
|
||||
if (!empty($this->else)) {
|
||||
$prefix .= ' ELSE ' . $this->else;
|
||||
}
|
||||
return $prefix . ' END';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Gii;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Config;
|
||||
use Snowflake\Abstracts\Input;
|
||||
use Snowflake\Exception\ConfigException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Command
|
||||
* @package HttpServer
|
||||
*/
|
||||
class Command extends \Console\Command
|
||||
{
|
||||
|
||||
public string $command = 'sw:gii';
|
||||
|
||||
|
||||
public string $description = './snowflake sw:gii make=model|controller|task|interceptor|limits|middleware name=xxxx';
|
||||
|
||||
|
||||
/**
|
||||
* @param Input $dtl
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onHandler(Input $dtl): array
|
||||
{
|
||||
/** @var Gii $gii */
|
||||
$gii = Snowflake::app()->get('gii');
|
||||
|
||||
$connections = Snowflake::app()->db;
|
||||
if ($dtl->exists('databases')) {
|
||||
return $gii->run($connections->get($dtl->get('databases')), $dtl);
|
||||
}
|
||||
|
||||
$array = [];
|
||||
foreach (Config::get('databases') as $key => $connection) {
|
||||
$array[$key] = $gii->run($connections->get($key), $dtl);
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Gii;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class GiiInterceptor
|
||||
* @package Gii
|
||||
*/
|
||||
class GiiInterceptor extends GiiBase
|
||||
{
|
||||
|
||||
public ?string $tableName = null;
|
||||
|
||||
|
||||
/**
|
||||
* @return bool|array
|
||||
* @throws Exception
|
||||
*/
|
||||
public function generate(): bool|array
|
||||
{
|
||||
|
||||
$managerName = $this->input->get('name', null);
|
||||
if (empty($managerName)) {
|
||||
throw new Exception('文件名称不能为空~');
|
||||
}
|
||||
$html = '<?php
|
||||
|
||||
|
||||
namespace App\Http\Interceptor;
|
||||
|
||||
';
|
||||
$file = APP_PATH . 'app/Http/Interceptor/' . $managerName . 'Interceptor.php';
|
||||
if (file_exists($file)) {
|
||||
try {
|
||||
$class = new \ReflectionClass('App\\Http\\Interceptor\\' . $managerName . 'Interceptor');
|
||||
|
||||
$html .= $this->getImports($file, $class);
|
||||
} catch (\Throwable $exception) {
|
||||
return logger()->addError($exception, 'throwable');
|
||||
}
|
||||
} else {
|
||||
$html .= '
|
||||
use Closure;
|
||||
use HttpServer\Http\Request;
|
||||
use HttpServer\IInterface\Interceptor;
|
||||
';
|
||||
}
|
||||
|
||||
|
||||
$managerName = ucfirst($managerName);
|
||||
$html .= '
|
||||
/**
|
||||
* Class ' . $managerName . 'Interceptor
|
||||
* @package App\Http\Interceptor
|
||||
*/
|
||||
class ' . $managerName . 'Interceptor implements Interceptor
|
||||
{';
|
||||
|
||||
if (isset($class)) {
|
||||
$html .= $this->getClassProperty($class);
|
||||
$html .= $this->getClassMethods($class);
|
||||
|
||||
$html .= '
|
||||
|
||||
}';
|
||||
} else {
|
||||
$html .= '
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Closure $closure
|
||||
* @return mixed
|
||||
*/
|
||||
public function Interceptor(Request $request, Closure $closure)
|
||||
{
|
||||
return $closure($request);
|
||||
}
|
||||
|
||||
|
||||
}';
|
||||
}
|
||||
|
||||
|
||||
if (file_exists($file)) {
|
||||
throw new Exception('File exists.');
|
||||
}
|
||||
|
||||
Snowflake::writeFile($file, $html);
|
||||
return [$managerName . 'Interceptor.php'];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Gii;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class GiiLimits
|
||||
* @package Gii
|
||||
*/
|
||||
class GiiLimits extends GiiBase
|
||||
{
|
||||
|
||||
public ?string $tableName = '';
|
||||
|
||||
|
||||
/**
|
||||
* @return string[]
|
||||
* @throws Exception
|
||||
*/
|
||||
public function generate(): array
|
||||
{
|
||||
|
||||
$managerName = $this->input->get('name', null);
|
||||
if (empty($managerName)) {
|
||||
throw new Exception('文件名称不能为空~');
|
||||
}
|
||||
$html = '<?php
|
||||
|
||||
|
||||
namespace App\Http\Limits;
|
||||
|
||||
use Closure;
|
||||
use HttpServer\Http\Request;
|
||||
use HttpServer\IInterface\Limits;
|
||||
|
||||
|
||||
';
|
||||
|
||||
$managerName = ucfirst($managerName);
|
||||
$html .= '
|
||||
/**
|
||||
* Class ' . $managerName . 'Limits
|
||||
* @package App\Http\Limits
|
||||
*/
|
||||
class ' . $managerName . 'Limits implements Limits
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param Closure $closure
|
||||
* @return mixed
|
||||
*/
|
||||
public function next(Request $request, Closure $closure)
|
||||
{
|
||||
return $closure($request);
|
||||
}
|
||||
|
||||
|
||||
}';
|
||||
|
||||
$file = APP_PATH . 'app/Http/Limits/' . $managerName . 'Limits.php';
|
||||
if (file_exists($file)) {
|
||||
throw new Exception('File exists.');
|
||||
}
|
||||
|
||||
Snowflake::writeFile($file, $html);
|
||||
return [$managerName . 'Limits.php'];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer\Abstracts;
|
||||
|
||||
|
||||
use Database\Connection;
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Config;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Exception\ConfigException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
|
||||
/**
|
||||
* Class Callback
|
||||
* @package HttpServer\Abstracts
|
||||
*/
|
||||
abstract class Callback extends HttpService
|
||||
{
|
||||
|
||||
|
||||
const EVENT_ERROR = 'WORKER:ERROR';
|
||||
const EVENT_STOP = 'WORKER:STOP';
|
||||
const EVENT_EXIT = 'WORKER:EXIT';
|
||||
|
||||
|
||||
private array $_MESSAGE = [
|
||||
self::EVENT_ERROR => 'The server error. at No.',
|
||||
self::EVENT_STOP => 'The server stop. at No.',
|
||||
self::EVENT_EXIT => 'The server exit. at No.',
|
||||
];
|
||||
|
||||
/**
|
||||
* @param $messageContent
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function system_mail($messageContent)
|
||||
{
|
||||
try {
|
||||
$email = Config::get('email');
|
||||
if (empty($email) || !$email['enable']) {
|
||||
return;
|
||||
}
|
||||
$transport = (new \Swift_SmtpTransport($email['host'], $email['465']))
|
||||
->setUsername($email['username'])
|
||||
->setPassword($email['password']);
|
||||
$mailer = new \Swift_Mailer($transport);
|
||||
|
||||
// Create a message
|
||||
$message = (new \Swift_Message('Wonderful Subject'))
|
||||
->setFrom([$email['send']['address'] => $email['send']['nickname']])
|
||||
->setBody('Here is the message itself');
|
||||
|
||||
foreach ($email['receive'] as $item) {
|
||||
$message->setTo([$item['address'], $item['address'] => $item['nickname']]);
|
||||
}
|
||||
$mailer->send($messageContent);
|
||||
} catch (\Throwable $e) {
|
||||
$this->addError($e, 'email');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws ConfigException
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function clearMysqlClient()
|
||||
{
|
||||
$databases = Config::get('databases', []);
|
||||
if (empty($databases)) {
|
||||
return;
|
||||
}
|
||||
$application = Snowflake::app();
|
||||
foreach ($databases as $name => $database) {
|
||||
/** @var Connection $connection */
|
||||
$connection = $application->get('databases.' . $name, false);
|
||||
if (empty($connection)) {
|
||||
continue;
|
||||
}
|
||||
$connection->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $clientInfo
|
||||
* @param string $event
|
||||
* @return string
|
||||
*/
|
||||
protected function getName(array $clientInfo, string $event): string
|
||||
{
|
||||
return 'listen ' . $clientInfo['server_port'] . ' ' . Event::SERVER_CONNECT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws ConfigException
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function clearRedisClient()
|
||||
{
|
||||
$redis = Snowflake::app()->getRedis();
|
||||
$redis->destroy();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer\Abstracts;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
|
||||
/**
|
||||
* Class HttpService
|
||||
* @package HttpServer\Abstracts
|
||||
*/
|
||||
abstract class HttpService extends Component
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param $message
|
||||
* @param string $category
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function write($message, $category = 'app')
|
||||
{
|
||||
$logger = Snowflake::app()->getLogger();
|
||||
$logger->write($message, $category);
|
||||
$logger->insert();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __get($name): mixed
|
||||
{
|
||||
if (method_exists($this, $name)) {
|
||||
return $this->{$name}();
|
||||
}
|
||||
$handler = 'get' . ucfirst($name);
|
||||
if (method_exists($this, $handler)) {
|
||||
return $this->{$handler}();
|
||||
}
|
||||
if (property_exists($this, $name)) {
|
||||
return $this->$name;
|
||||
}
|
||||
$message = sprintf('method %s::%s not exists.', static::class, $name);
|
||||
throw new Exception($message);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/11/8 0008
|
||||
* Time: 18:37
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
namespace HttpServer\Abstracts;
|
||||
|
||||
|
||||
use Swoole\WebSocket\Server;
|
||||
|
||||
/**
|
||||
* Class ServerBase
|
||||
* @package Snowflake\Snowflake\Server
|
||||
*/
|
||||
abstract class ServerBase extends HttpService
|
||||
{
|
||||
|
||||
/** @var Server */
|
||||
protected Server $server;
|
||||
|
||||
/**
|
||||
* @return Server
|
||||
*/
|
||||
public function getServer(): Server
|
||||
{
|
||||
return $this->server;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $server
|
||||
*/
|
||||
public function setServer($server)
|
||||
{
|
||||
$this->server = $server;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,149 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Created by PhpStorm.
|
||||
* User: whwyy
|
||||
* Date: 2018/5/24 0024
|
||||
* Time: 11:34
|
||||
*/
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer\Client;
|
||||
|
||||
use Exception;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use Swoole\Coroutine\Http\Client as SClient;
|
||||
|
||||
/**
|
||||
* Class Client
|
||||
* @package Snowflake\Snowflake\Http
|
||||
*/
|
||||
class Client extends ClientAbstracts
|
||||
{
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param $path
|
||||
* @param array $params
|
||||
* @return array|string|Result
|
||||
* @throws Exception
|
||||
*/
|
||||
public function request(string $method, $path, $params = []): array|string|Result
|
||||
{
|
||||
return $this->setMethod($method)
|
||||
->coroutine(
|
||||
$this->matchHost($path),
|
||||
$this->paramEncode($params)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $url
|
||||
* @param array $data
|
||||
* @return array|string|Result
|
||||
* @throws Exception
|
||||
* 使用swoole协程方式请求
|
||||
*/
|
||||
private function coroutine($url, $data = []): array|string|Result
|
||||
{
|
||||
try {
|
||||
$client = $this->generate_client($data, ...$url);
|
||||
$this->setData('');
|
||||
if ($client->statusCode < 0) {
|
||||
throw new Exception($client->errMsg);
|
||||
}
|
||||
$body = $this->resolve($client->getHeaders(), $client->body);
|
||||
if (in_array($client->getStatusCode(), [200, 201])) {
|
||||
return $this->structure($body, $data, $client->getHeaders());
|
||||
}
|
||||
if (is_string($body)) {
|
||||
$message = 'Request error code ' . $client->getStatusCode();
|
||||
} else {
|
||||
$message = $this->searchMessageByData($body);
|
||||
}
|
||||
return $this->fail($client->getStatusCode(), $message, $body, $client->getHeaders());
|
||||
} catch (\Throwable $exception) {
|
||||
$this->addError($exception, 'rpc');
|
||||
return $this->fail(500, $exception->getMessage(), [
|
||||
'file' => $exception->getFile(),
|
||||
'line' => $exception->getLine()
|
||||
], []);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param $host
|
||||
* @param $isHttps
|
||||
* @param $path
|
||||
* @return SClient
|
||||
*/
|
||||
private function generate_client($data, $host, $isHttps, $path): SClient
|
||||
{
|
||||
if ($isHttps || $this->isSSL()) {
|
||||
$client = new SClient($host, 443, true);
|
||||
} else {
|
||||
$client = new SClient($host, $this->getPort(), false);
|
||||
}
|
||||
$client->set($this->settings());
|
||||
if (!empty($this->getAgent())) {
|
||||
$this->addHeader('User-Agent', $this->getAgent());
|
||||
}
|
||||
$client->setHeaders($this->getHeader());
|
||||
$client->setMethod(strtoupper($this->getMethod()));
|
||||
$client->execute($this->setParams($client, $path, $data));
|
||||
$client->close();
|
||||
return $client;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $client
|
||||
* @param $path
|
||||
* @param $data
|
||||
* @return string
|
||||
*/
|
||||
private function setParams(SClient $client, $path, $data): string
|
||||
{
|
||||
if ($this->isGet()) {
|
||||
if (!empty($data)) $path .= '?' . $data;
|
||||
if (!empty($this->getData())) {
|
||||
$client->setData($this->getData());
|
||||
}
|
||||
} else {
|
||||
if (!empty($this->getData())) {
|
||||
$client->setData($this->getData());
|
||||
} else {
|
||||
$client->setData($this->mergeParams($data));
|
||||
}
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
#[Pure] private function settings(): array
|
||||
{
|
||||
$sslCert = $this->getSslCertFile();
|
||||
$sslKey = $this->getSslKeyFile();
|
||||
$sslCa = $this->getCa();
|
||||
|
||||
$params = [];
|
||||
if ($this->getConnectTimeout() > 0) {
|
||||
$params['timeout'] = $this->getConnectTimeout();
|
||||
}
|
||||
if (empty($sslCert) || empty($sslKey) || empty($sslCa)) {
|
||||
return $params;
|
||||
}
|
||||
|
||||
$params['ssl_host_name'] = $this->getHost();
|
||||
$params['ssl_cert_file'] = $this->getSslCertFile();
|
||||
$params['ssl_key_file'] = $this->getSslKeyFile();
|
||||
$params['ssl_verify_peer'] = true;
|
||||
$params['ssl_cafile'] = $sslCa;
|
||||
|
||||
return $params;
|
||||
}
|
||||
}
|
||||
@@ -1,807 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace HttpServer\Client;
|
||||
|
||||
|
||||
use Closure;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Core\Help;
|
||||
use Swoole\Coroutine\System;
|
||||
|
||||
defined('SPLIT_URL') or define('SPLIT_URL', '/(http[s]?:\/\/)?(([\w\-_]+\.)+\w+(:\d+)?)((\/[a-zA-Z0-9\-]+)+[\/]?(\?[a-zA-Z]+=.*)?)?/');
|
||||
|
||||
|
||||
/**
|
||||
* Class ClientAbstracts
|
||||
* @package HttpServer\Client
|
||||
*/
|
||||
abstract class ClientAbstracts extends Component implements IClient
|
||||
{
|
||||
|
||||
const POST = 'post';
|
||||
const UPLOAD = 'upload';
|
||||
const GET = 'get';
|
||||
const DELETE = 'delete';
|
||||
const OPTIONS = 'options';
|
||||
const HEAD = 'head';
|
||||
const PUT = 'put';
|
||||
|
||||
private string $host = '';
|
||||
|
||||
private array $header = [];
|
||||
|
||||
private int $timeout = 0;
|
||||
|
||||
private ?Closure $callback = null;
|
||||
private string $method = 'get';
|
||||
|
||||
private bool $isSSL = false;
|
||||
private string $agent = '';
|
||||
private string $errorCodeField = '';
|
||||
private string $errorMsgField = '';
|
||||
private bool $use_swoole = false;
|
||||
|
||||
private string $ssl_cert_file = '';
|
||||
private string $ssl_key_file = '';
|
||||
private string $ca = '';
|
||||
private int $port = 80;
|
||||
|
||||
/** @var string $_message 错误信息 */
|
||||
private string $_message = '';
|
||||
private string $_data = '';
|
||||
|
||||
private int $connect_timeout = 1;
|
||||
|
||||
|
||||
/**
|
||||
* @return static
|
||||
*/
|
||||
#[Pure] public static function NewRequest(): static
|
||||
{
|
||||
return new static();
|
||||
}
|
||||
|
||||
|
||||
protected function cleanData(): void
|
||||
{
|
||||
$this->_data = '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param array $params
|
||||
* @return array|int|string|Result
|
||||
* @throws
|
||||
*/
|
||||
public function post(string $path, array $params = []): array|int|string|Result
|
||||
{
|
||||
return $this->request(self::POST, $path, $params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|int|string|Result
|
||||
*/
|
||||
public function put(string $path, array $params = []): array|int|string|Result
|
||||
{
|
||||
return $this->request(self::PUT, $path, $params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $contentType
|
||||
*/
|
||||
public function setContentType(string $contentType): void
|
||||
{
|
||||
$this->header['Content-Type'] = $contentType;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|int|string|Result
|
||||
*/
|
||||
public function head(string $path, array $params = []): array|int|string|Result
|
||||
{
|
||||
return $this->request(self::HEAD, $path, $params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|int|string|Result
|
||||
*/
|
||||
public function get(string $path, array $params = []): array|int|string|Result
|
||||
{
|
||||
return $this->request(self::GET, $path, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|int|string|Result
|
||||
*/
|
||||
public function option(string $path, array $params = []): array|int|string|Result
|
||||
{
|
||||
return $this->request(self::OPTIONS, $path, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|int|string|Result
|
||||
*/
|
||||
public function delete(string $path, array $params = []): array|int|string|Result
|
||||
{
|
||||
return $this->request(self::DELETE, $path, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|int|string|Result
|
||||
*/
|
||||
public function options(string $path, array $params = []): array|int|string|Result
|
||||
{
|
||||
return $this->request(self::OPTIONS, $path, $params);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|int|string|Result
|
||||
*/
|
||||
public function upload(string $path, array $params = []): array|int|string|Result
|
||||
{
|
||||
return $this->request(self::UPLOAD, $path, $params);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getHost(): string
|
||||
{
|
||||
return $this->host;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
protected function getHostPort(): int
|
||||
{
|
||||
if (!empty($this->getPort())) {
|
||||
return $this->getPort();
|
||||
}
|
||||
$port = 80;
|
||||
if ($this->isSSL()) $port = 443;
|
||||
return $port;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
*/
|
||||
public function setHost(string $host): void
|
||||
{
|
||||
$this->host = $host;
|
||||
if ($this->use_swoole) {
|
||||
$this->host = System::gethostbyname($host);
|
||||
}
|
||||
$this->addHeader('Host', $host);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getHeader(): array
|
||||
{
|
||||
return $this->header;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $header
|
||||
*/
|
||||
public function setHeader(array $header): void
|
||||
{
|
||||
$this->header = $header;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $header
|
||||
* @return array
|
||||
*/
|
||||
public function setHeaders(array $header): array
|
||||
{
|
||||
if (empty($header)) {
|
||||
return [];
|
||||
}
|
||||
foreach ($header as $key => $val) {
|
||||
$this->header[$key] = $val;
|
||||
}
|
||||
return $this->header;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $value
|
||||
*/
|
||||
public function addHeader($key, $value): void
|
||||
{
|
||||
$this->header[$key] = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getTimeout(): int
|
||||
{
|
||||
return $this->timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $value
|
||||
*/
|
||||
public function setTimeout(int $value): void
|
||||
{
|
||||
$this->timeout = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Closure|null
|
||||
*/
|
||||
public function getCallback(): ?Closure
|
||||
{
|
||||
return $this->callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Closure|null $value
|
||||
*/
|
||||
public function setCallback(?Closure $value): void
|
||||
{
|
||||
$this->callback = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMethod(): string
|
||||
{
|
||||
return $this->method;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @return static
|
||||
*/
|
||||
public function setMethod(string $value): static
|
||||
{
|
||||
$this->method = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isSSL(): bool
|
||||
{
|
||||
return $this->isSSL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $isSSL
|
||||
*/
|
||||
public function setIsSSL(bool $isSSL): void
|
||||
{
|
||||
$this->isSSL = $isSSL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getAgent(): string
|
||||
{
|
||||
return $this->agent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $agent
|
||||
*/
|
||||
public function setAgent(string $agent): void
|
||||
{
|
||||
$this->agent = $agent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getErrorCodeField(): string
|
||||
{
|
||||
return $this->errorCodeField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $errorCodeField
|
||||
*/
|
||||
public function setErrorCodeField(string $errorCodeField): void
|
||||
{
|
||||
$this->errorCodeField = $errorCodeField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getErrorMsgField(): string
|
||||
{
|
||||
return $this->errorMsgField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $errorMsgField
|
||||
*/
|
||||
public function setErrorMsgField(string $errorMsgField): void
|
||||
{
|
||||
$this->errorMsgField = $errorMsgField;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function isUseSwoole(): bool
|
||||
{
|
||||
return $this->use_swoole;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $use_swoole
|
||||
*/
|
||||
public function setUseSwoole(bool $use_swoole): void
|
||||
{
|
||||
$this->use_swoole = $use_swoole;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSslCertFile(): string
|
||||
{
|
||||
return $this->ssl_cert_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $ssl_cert_file
|
||||
*/
|
||||
public function setSslCertFile(string $ssl_cert_file): void
|
||||
{
|
||||
$this->ssl_cert_file = $ssl_cert_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getSslKeyFile(): string
|
||||
{
|
||||
return $this->ssl_key_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $ssl_key_file
|
||||
*/
|
||||
public function setSslKeyFile(string $ssl_key_file): void
|
||||
{
|
||||
$this->ssl_key_file = $ssl_key_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getCa(): string
|
||||
{
|
||||
return $this->ca;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $ssl_key_file
|
||||
*/
|
||||
public function setCa(string $ssl_key_file): void
|
||||
{
|
||||
$this->ca = $ssl_key_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getPort(): int
|
||||
{
|
||||
if ($this->isSSL()) {
|
||||
return 443;
|
||||
}
|
||||
if (empty($this->port)) {
|
||||
return 80;
|
||||
}
|
||||
return $this->port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $port
|
||||
*/
|
||||
public function setPort(int $port): void
|
||||
{
|
||||
$this->port = $port;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getMessage(): string
|
||||
{
|
||||
return $this->_message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
*/
|
||||
public function setMessage(string $message): void
|
||||
{
|
||||
$this->_message = $message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
public function getData(): string
|
||||
{
|
||||
return $this->_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
*/
|
||||
public function setData(string $data): void
|
||||
{
|
||||
$this->_data = $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function getConnectTimeout(): int
|
||||
{
|
||||
return $this->connect_timeout;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $connect_timeout
|
||||
*/
|
||||
public function setConnectTimeout(int $connect_timeout): void
|
||||
{
|
||||
$this->connect_timeout = $connect_timeout;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $host
|
||||
* @return string|string[]
|
||||
*/
|
||||
protected function replaceHost($host): array|string
|
||||
{
|
||||
if ($this->isHttp($host)) {
|
||||
return str_replace('http://', '', $host);
|
||||
}
|
||||
if ($this->isHttps($host)) {
|
||||
return str_replace('https://', '', $host);
|
||||
}
|
||||
return $host;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $url
|
||||
* @return false|int
|
||||
*/
|
||||
protected function checkIsIp($url): bool|int
|
||||
{
|
||||
return preg_match('/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/', $url);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $url
|
||||
* @return bool
|
||||
*/
|
||||
#[Pure] protected function isHttp($url): bool
|
||||
{
|
||||
return str_starts_with($url, 'http://');
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $url
|
||||
* @return bool
|
||||
*/
|
||||
#[Pure] protected function isHttps($url): bool
|
||||
{
|
||||
return str_starts_with($url, 'https://');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $newData
|
||||
* @return string
|
||||
*/
|
||||
protected function mergeParams($newData): string
|
||||
{
|
||||
if (!is_string($newData)) {
|
||||
return $this->toRequest($newData);
|
||||
}
|
||||
return $newData;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return string
|
||||
*/
|
||||
protected function toRequest($data): string
|
||||
{
|
||||
if (is_string($data)) {
|
||||
return $data;
|
||||
}
|
||||
$contentType = 'application/x-www-form-urlencoded';
|
||||
if (isset($this->header['Content-Type'])) {
|
||||
$contentType = $this->header['Content-Type'];
|
||||
} else if (isset($this->header['content-type'])) {
|
||||
$contentType = $this->header['content-type'];
|
||||
}
|
||||
if (str_contains($contentType, 'json')) {
|
||||
return Help::toJson($data);
|
||||
} else if (str_contains($contentType, 'xml')) {
|
||||
return Help::toXml($data);
|
||||
} else {
|
||||
return http_build_query($data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @param $body
|
||||
* @return array|string|null
|
||||
*/
|
||||
protected function resolve($data, $body): array|string|null
|
||||
{
|
||||
if (is_array($body)) {
|
||||
return $body;
|
||||
}
|
||||
$type = $data['content-type'] ?? $data['Content-Type'] ?? 'text/html';
|
||||
if (str_contains($type, 'text/html')) {
|
||||
return $body;
|
||||
} else if (str_contains($type, 'json')) {
|
||||
return json_decode($body, true);
|
||||
} else if (str_contains($type, 'xml')) {
|
||||
return Help::xmlToArray($body);
|
||||
} else if (str_contains($type, 'plain')) {
|
||||
return Help::toArray($body);
|
||||
}
|
||||
return $body;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $body
|
||||
* @param $_data
|
||||
* @param array $header
|
||||
* @param int $statusCode
|
||||
* @return mixed 构建返回体
|
||||
* 构建返回体
|
||||
*/
|
||||
protected function structure($body, $_data, $header = [], $statusCode = 200): mixed
|
||||
{
|
||||
if ($this->callback instanceof Closure) {
|
||||
$result = call_user_func($this->callback, $body, $_data, $header);
|
||||
} else {
|
||||
$result = $this->parseResult($body, $header, $statusCode);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $body
|
||||
* @param $header
|
||||
* @param $statusCode
|
||||
* @return Result
|
||||
*/
|
||||
private function parseResult($body, $header, $statusCode): Result
|
||||
{
|
||||
if (is_string($body)) {
|
||||
$result['code'] = 0;
|
||||
$result['message'] = '';
|
||||
} else {
|
||||
$result['code'] = $body[$this->errorCodeField] ?? 0;
|
||||
$result['message'] = $this->searchMessageByData($body);
|
||||
}
|
||||
$result['data'] = $body;
|
||||
$result['header'] = $header;
|
||||
$result['httpStatus'] = $statusCode;
|
||||
return new Result($result);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $body
|
||||
* @return mixed
|
||||
*/
|
||||
protected function searchMessageByData($body): mixed
|
||||
{
|
||||
$parent = [];
|
||||
if (empty($this->errorMsgField)) {
|
||||
return 'system success.';
|
||||
}
|
||||
$explode = explode('.', $this->errorMsgField);
|
||||
if (!isset($body[$explode[0]])) {
|
||||
return 'system success.';
|
||||
}
|
||||
foreach ($explode as $item) {
|
||||
if (empty($item)) {
|
||||
continue;
|
||||
}
|
||||
if (empty($parent)) {
|
||||
$parent = $body[$item];
|
||||
continue;
|
||||
}
|
||||
if (is_string($parent) || !isset($parent[$item])) {
|
||||
break;
|
||||
}
|
||||
$parent = $parent[$item];
|
||||
}
|
||||
return !empty($parent) ? $parent : 'system success.';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* check isPost Request
|
||||
*/
|
||||
#[Pure] public function isPost(): bool
|
||||
{
|
||||
return strtolower($this->method) === self::POST;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
* check isPost Request
|
||||
*/
|
||||
#[Pure] public function isUpload(): bool
|
||||
{
|
||||
return strtolower($this->method) === self::UPLOAD;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*
|
||||
* check isGet Request
|
||||
*/
|
||||
#[Pure] public function isGet(): bool
|
||||
{
|
||||
return strtolower($this->method) === self::GET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $arr
|
||||
*
|
||||
* @return array|string
|
||||
* 将请求参数进行编码
|
||||
*/
|
||||
#[Pure] protected function paramEncode($arr): array|string
|
||||
{
|
||||
if (!is_array($arr)) {
|
||||
return $arr;
|
||||
}
|
||||
$_tmp = [];
|
||||
foreach ($arr as $Key => $val) {
|
||||
$_tmp[$Key] = $val;
|
||||
}
|
||||
if ($this->isGet()) {
|
||||
return http_build_query($_tmp);
|
||||
}
|
||||
return $_tmp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $string
|
||||
* @return array
|
||||
*/
|
||||
protected function matchHost(string $string): array
|
||||
{
|
||||
if (($parse = isUrl($string, true)) === false) {
|
||||
return $this->defaultString($string);
|
||||
}
|
||||
[$isHttps, $domain, $port, $path] = $parse;
|
||||
if (str_contains($domain, ':' . $port)) {
|
||||
$domain = str_replace(':' . $port, '', $domain);
|
||||
}
|
||||
$this->port = $isHttps ? 443 : $this->port;
|
||||
if (isIp($domain)) {
|
||||
$this->host = $domain;
|
||||
} else if ($this->isUseSwoole()) {
|
||||
$this->host = System::gethostbyname($domain) ?? $domain;
|
||||
} else {
|
||||
$this->host = $domain;
|
||||
}
|
||||
$this->header['Host'] = $domain;
|
||||
if (strpos($path, '/') !== 0) {
|
||||
$path = '/' . $path;
|
||||
}
|
||||
return [$this->host, $isHttps, $path];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $string
|
||||
* @return array
|
||||
*/
|
||||
private function defaultString($string): array
|
||||
{
|
||||
$host = $this->getHost();
|
||||
if ($string == '/') {
|
||||
$string = '';
|
||||
} else if (strpos($string, '/') !== 0) {
|
||||
$string = '/' . $string;
|
||||
}
|
||||
return [$host, $this->isSSL(), $string];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param $params
|
||||
* @return string
|
||||
*/
|
||||
#[Pure] protected function joinGetParams($path, $params): string
|
||||
{
|
||||
if (empty($params)) {
|
||||
return $path;
|
||||
}
|
||||
if (!is_string($params)) {
|
||||
$params = http_build_query($params);
|
||||
}
|
||||
if (str_contains($path, '?')) {
|
||||
[$path, $getParams] = explode('?', $path);
|
||||
}
|
||||
if (!isset($getParams) || empty($getParams)) {
|
||||
return $path . '?' . $params;
|
||||
}
|
||||
return $path . '?' . $params . '&' . $getParams;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $code
|
||||
* @param $message
|
||||
* @param $data
|
||||
* @param $header
|
||||
* @return Result
|
||||
*/
|
||||
protected function fail($code, $message, $data = [], $header = []): Result
|
||||
{
|
||||
return new Result([
|
||||
'code' => $code,
|
||||
'message' => $message,
|
||||
'data' => $data,
|
||||
'header' => $header,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,222 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer\Client;
|
||||
|
||||
|
||||
use Exception;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
|
||||
|
||||
/**
|
||||
* Class Curl
|
||||
* @package HttpServer\Client
|
||||
*/
|
||||
class Curl extends ClientAbstracts
|
||||
{
|
||||
|
||||
/**
|
||||
* @param $method
|
||||
* @param $path
|
||||
* @param array $params
|
||||
* @return Result|array|string
|
||||
* @throws Exception
|
||||
*/
|
||||
public function request($method, $path, $params = []): Result|array|string
|
||||
{
|
||||
if ($method == self::GET) {
|
||||
$path = $this->joinGetParams($path, $params);
|
||||
}
|
||||
return $this->execute($this->getCurlHandler($path, $method, $params));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param $method
|
||||
* @param $params
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getCurlHandler($path, $method, $params): mixed
|
||||
{
|
||||
[$host, $isHttps, $path] = $this->matchHost($path);
|
||||
|
||||
$host = $isHttps ? 'https://' . $host : 'http://' . $host;
|
||||
if ($this->getPort() != 443 && $this->getPort() != 80) {
|
||||
$host .= ':' . $this->getPort();
|
||||
}
|
||||
|
||||
$resource = $this->do(curl_init($host . $path), $host . $path, $method);
|
||||
if ($isHttps !== false) {
|
||||
$this->curlHandlerSslSet($resource);
|
||||
}
|
||||
if (empty($params) && empty($this->getData())) {
|
||||
return $resource;
|
||||
}
|
||||
|
||||
if (!empty($this->getData())) {
|
||||
curl_setopt($resource, CURLOPT_POSTFIELDS, $this->getData());
|
||||
} else if ($method === self::POST) {
|
||||
curl_setopt($resource, CURLOPT_POSTFIELDS, $this->mergeParams($params));
|
||||
} else if ($method === self::UPLOAD) {
|
||||
curl_setopt($resource, CURLOPT_POSTFIELDS, $params);
|
||||
}
|
||||
return $resource;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $resource
|
||||
* @return bool
|
||||
* @throws Exception
|
||||
*/
|
||||
private function curlHandlerSslSet($resource): mixed
|
||||
{
|
||||
if (!empty($this->ssl_key)) {
|
||||
if (!file_exists($this->ssl_key)) {
|
||||
throw new Exception('SSL protocol certificate not found.');
|
||||
}
|
||||
curl_setopt($resource, CURLOPT_SSLKEY, $this->getSslKeyFile());
|
||||
}
|
||||
if (!empty($this->ssl_cert)) {
|
||||
if (!!file_exists($this->ssl_cert)) {
|
||||
throw new Exception('SSL protocol certificate not found.');
|
||||
}
|
||||
curl_setopt($resource, CURLOPT_SSLCERT, $this->getSslCertFile());
|
||||
}
|
||||
return $resource;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $resource
|
||||
* @param $path
|
||||
* @param $method
|
||||
* @return resource
|
||||
* @throws Exception
|
||||
*/
|
||||
private function do($resource, $path, $method)
|
||||
{
|
||||
curl_setopt($resource, CURLOPT_URL, $path);
|
||||
curl_setopt($resource, CURLOPT_TIMEOUT, $this->getTimeout()); // 超时设置
|
||||
curl_setopt($resource, CURLOPT_CONNECTTIMEOUT, $this->getConnectTimeout()); // 超时设置
|
||||
|
||||
curl_setopt($resource, CURLOPT_HEADER, true);
|
||||
curl_setopt($resource, CURLOPT_FAILONERROR, true);
|
||||
|
||||
curl_setopt($resource, CURLOPT_HTTPHEADER, $this->parseHeaderMat());
|
||||
if (defined('CURLOPT_SSL_FALSESTART')) {
|
||||
curl_setopt($resource, CURLOPT_SSL_FALSESTART, true);
|
||||
}
|
||||
curl_setopt($resource, CURLOPT_FORBID_REUSE, false);
|
||||
curl_setopt($resource, CURLOPT_FRESH_CONNECT, false);
|
||||
|
||||
if (!empty($this->getAgent())) {
|
||||
curl_setopt($resource, CURLOPT_USERAGENT, $this->getAgent());
|
||||
}
|
||||
|
||||
curl_setopt($resource, CURLOPT_NOBODY, FALSE);
|
||||
curl_setopt($resource, CURLOPT_RETURNTRANSFER, TRUE);//返回内容
|
||||
curl_setopt($resource, CURLOPT_FOLLOWLOCATION, TRUE);// 跟踪重定向
|
||||
curl_setopt($resource, CURLOPT_ENCODING, 'gzip,deflate');
|
||||
if ($method === self::POST || $method == self::UPLOAD) {
|
||||
curl_setopt($resource, CURLOPT_POST, 1);
|
||||
}
|
||||
curl_setopt($resource, CURLOPT_CUSTOMREQUEST, strtoupper($method));
|
||||
|
||||
return $resource;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $curl
|
||||
* @return Result|bool|array|string
|
||||
* @throws Exception
|
||||
*/
|
||||
private function execute($curl): Result|bool|array|string
|
||||
{
|
||||
defer(fn() => $this->cleanData());
|
||||
$output = curl_exec($curl);
|
||||
if ($output === false) {
|
||||
return $this->fail(400, curl_error($curl));
|
||||
}
|
||||
return $this->parseResponse($curl, $output);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $curl
|
||||
* @param $output
|
||||
* @param array $params
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
private function parseResponse($curl, $output, $params = []): mixed
|
||||
{
|
||||
curl_close($curl);
|
||||
if ($output === FALSE) {
|
||||
return $this->fail(500, $output);
|
||||
}
|
||||
[$header, $body, $status] = $this->explode($output);
|
||||
if ($status != 200 && $status != 201) {
|
||||
$data = $this->fail($status, $body, [], $header);
|
||||
} else {
|
||||
$data = $this->structure($body, $params, $header);
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $output
|
||||
* @return array
|
||||
* @throws Exception
|
||||
*/
|
||||
private function explode($output): array
|
||||
{
|
||||
if (empty($output) || !str_contains($output, "\r\n\r\n")) {
|
||||
throw new Exception('Get data null.');
|
||||
}
|
||||
|
||||
[$header, $body] = explode("\r\n\r\n", $output, 2);
|
||||
if ($header == 'HTTP/1.1 100 Continue') {
|
||||
[$header, $body] = explode("\r\n\r\n", $body, 2);
|
||||
}
|
||||
|
||||
$header = explode("\r\n", $header);
|
||||
|
||||
$status = (int)explode(' ', trim($header[0]))[1];
|
||||
$header = $this->headerFormat($header);
|
||||
|
||||
return [$header, $this->resolve($header, $body), $status];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $headers
|
||||
* @return array
|
||||
*/
|
||||
private function headerFormat($headers): array
|
||||
{
|
||||
$_tmp = [];
|
||||
foreach ($headers as $key => $val) {
|
||||
$trim = explode(': ', trim($val));
|
||||
|
||||
$_tmp[strtolower($trim[0])] = $trim[1] ?? '';
|
||||
}
|
||||
return $_tmp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
#[Pure] private function parseHeaderMat(): array
|
||||
{
|
||||
$headers = [];
|
||||
foreach ($this->getHeader() as $key => $val) {
|
||||
$headers[$key] = $key . ': ' . $val;
|
||||
}
|
||||
return array_values($headers);
|
||||
}
|
||||
}
|
||||
@@ -1,344 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer\Client;
|
||||
|
||||
|
||||
use Exception;
|
||||
use HttpServer\Http\Context;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Channel;
|
||||
use Snowflake\Core\Json;
|
||||
use Snowflake\Core\Xml;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Snowflake;
|
||||
use Swoole\Coroutine\Http2\Client as H2Client;
|
||||
use Swoole\Http2\Request;
|
||||
use Swoole\Http2\Response;
|
||||
|
||||
|
||||
/**
|
||||
* Class Http2
|
||||
* @package HttpServer\Client
|
||||
*/
|
||||
class Http2 extends Component
|
||||
{
|
||||
|
||||
|
||||
private array $_clients = [];
|
||||
|
||||
|
||||
private Channel $channel;
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$this->channel = Snowflake::getApp('channel');
|
||||
|
||||
Event::on(Event::SYSTEM_RESOURCE_RELEASES, [$this, 'releases']);
|
||||
Event::on(Event::SYSTEM_RESOURCE_CLEAN, [$this, 'clean']);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function releases()
|
||||
{
|
||||
foreach ($this->_clients as $name => $client) {
|
||||
/** @var H2Client $client */
|
||||
$client->close();
|
||||
$this->channel->push($client, 'http2.' . $name);
|
||||
}
|
||||
$this->_clients = [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 清空
|
||||
*/
|
||||
public function clean()
|
||||
{
|
||||
foreach ($this->_clients as $client) {
|
||||
/** @var H2Client $client */
|
||||
$client->close();
|
||||
}
|
||||
$this->_clients = [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param bool $isRecv
|
||||
* @return Http2
|
||||
*/
|
||||
public function setIsRecv(bool $isRecv): static
|
||||
{
|
||||
Context::setContext('http2isRecv', $isRecv);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $timeout
|
||||
* @return Http2
|
||||
*/
|
||||
public function setTimeout(int $timeout): static
|
||||
{
|
||||
Context::setContext('http2timeout', $timeout);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $headers
|
||||
* @return Http2
|
||||
*/
|
||||
public function setHeader(array $headers): static
|
||||
{
|
||||
Context::setContext('http2Headers', $headers);
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $domain
|
||||
* @param $path
|
||||
* @param array $params
|
||||
* @param int $timeout
|
||||
* @return Result
|
||||
* @throws Exception
|
||||
*/
|
||||
public function get($domain, $path, $params = [], $timeout = -1): Result
|
||||
{
|
||||
$request = $this->dispatch($domain, $path, 'GET', $params, $timeout);
|
||||
|
||||
return new Result(['code' => 0, 'data' => $request]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $domain
|
||||
* @param $path
|
||||
* @param array $params
|
||||
* @param int $timeout
|
||||
* @return Result
|
||||
* @throws Exception
|
||||
*/
|
||||
public function post($domain, $path, $params = [], $timeout = -1): Result
|
||||
{
|
||||
$request = $this->dispatch($domain, $path, 'POST', $params, $timeout);
|
||||
|
||||
return new Result(['code' => 0, 'data' => $request]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $domain
|
||||
* @param $path
|
||||
* @param array $params
|
||||
* @param int $timeout
|
||||
* @return Result
|
||||
* @throws Exception
|
||||
*/
|
||||
public function upload($domain, $path, $params = [], $timeout = -1): Result
|
||||
{
|
||||
$request = $this->dispatch($domain, $path, 'POST', $params, $timeout, true);
|
||||
|
||||
return new Result(['code' => 0, 'data' => $request]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $domain
|
||||
* @param $path
|
||||
* @param array $params
|
||||
* @param int $timeout
|
||||
* @return Result
|
||||
* @throws Exception
|
||||
*/
|
||||
public function delete($domain, $path, $params = [], $timeout = -1): Result
|
||||
{
|
||||
$request = $this->dispatch($domain, $path, 'DELETE', $params, $timeout);
|
||||
|
||||
return new Result(['code' => 0, 'data' => $request]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $domain
|
||||
* @param $path
|
||||
* @param $method
|
||||
* @param array $params
|
||||
* @param int $timeout
|
||||
* @param bool $isUpload
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
private function dispatch($domain, $path, $method, $params = [], $timeout = -1, $isUpload = false): mixed
|
||||
{
|
||||
[$domain, $isSsl] = $this->clear($domain);
|
||||
|
||||
$request = $this->getRequest($path, $method, $params, $isUpload);
|
||||
$request->headers = array_merge($request->headers, [
|
||||
'Host' => $domain
|
||||
]);
|
||||
defer(fn() => $this->channel->push($request, 'request.' . $method . $path));
|
||||
return $this->doRequest($request, $domain, $isSsl, $timeout);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $domain
|
||||
* @return array
|
||||
*/
|
||||
private function clear($domain): array
|
||||
{
|
||||
if (str_starts_with($domain, 'https://')) {
|
||||
return [str_replace('https://', '', $domain), true];
|
||||
} else {
|
||||
return [str_replace('http://', '', $domain), false];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @param $domain
|
||||
* @param $ssl
|
||||
* @param $timeout
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
private function doRequest(Request $request, $domain, $ssl, $timeout): mixed
|
||||
{
|
||||
$client = $this->getClient($domain, $ssl, $timeout);
|
||||
defer(fn() => $this->channel->push($client, 'http2.' . $domain));
|
||||
$client->send($request);
|
||||
if (Context::getContext('http2isRecv') === false) {
|
||||
return null;
|
||||
}
|
||||
return $this->recv($client);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $client
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
private function recv($client): mixed
|
||||
{
|
||||
/** @var Response $response */
|
||||
if (!Context::hasContext('http2timeout')) {
|
||||
$response = $client->recv();
|
||||
} else {
|
||||
$response = $client->recv((int)Context::getContext('http2timeout'));
|
||||
}
|
||||
if ($response === false || $response->statusCode > 200) {
|
||||
throw new Exception($client->errMsg, $client->errCode);
|
||||
}
|
||||
$header = $response->headers['content-type'];
|
||||
if (str_starts_with($header, 'application/json;')) {
|
||||
return Json::decode($response->data);
|
||||
} else if (str_starts_with($header, 'application/xml;')) {
|
||||
return Xml::toArray($response->data);
|
||||
} else {
|
||||
return $response->data;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $domain
|
||||
* @param $path
|
||||
* @param array $params
|
||||
* @param int $timeout
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function put($domain, $path, $params = [], $timeout = -1): Result
|
||||
{
|
||||
$request = $this->dispatch($domain, $path, 'PUT', $params, $timeout);
|
||||
|
||||
return new Result(['code' => 0, 'data' => $request]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $path
|
||||
* @param $method
|
||||
* @param $params
|
||||
* @param bool $isUpload
|
||||
* @return Request
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getRequest($path, $method, $params, $isUpload = false): Request
|
||||
{
|
||||
if (!str_starts_with($path, '/')) {
|
||||
$path = '/' . $path;
|
||||
}
|
||||
$channel = Snowflake::app()->getChannel();
|
||||
$request = $channel->pop('request.' . $method . $path, function () use ($path, $method) {
|
||||
$request = new Request();
|
||||
$request->method = $method;
|
||||
$request->path = $path;
|
||||
return $request;
|
||||
});
|
||||
if ($method === 'GET') {
|
||||
$request->path .= '?' . http_build_query($params);
|
||||
} else {
|
||||
$request->data = !is_string($params) && !$isUpload ? Json::encode($params) : $params;
|
||||
}
|
||||
$request->headers = Context::getContext('http2Headers');
|
||||
return $request;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $domain
|
||||
* @param bool $isSsl
|
||||
* @param int $timeout
|
||||
* @return H2Client
|
||||
* @throws Exception
|
||||
*/
|
||||
private function getClient($domain, $isSsl = false, $timeout = -1): H2Client
|
||||
{
|
||||
if (isset($this->_clients[$domain])) {
|
||||
return $this->_clients[$domain];
|
||||
}
|
||||
$pool = Snowflake::app()->getChannel();
|
||||
/** @var H2Client $client */
|
||||
$client = $pool->pop('http2.' . $domain, function () use ($domain, $isSsl, $timeout) {
|
||||
return $this->newRequest($domain, $isSsl, $timeout);
|
||||
});
|
||||
if ((!$client->connected || !$client->ping()) && !$client->connect()) {
|
||||
throw new Exception($client->errMsg, $client->errCode);
|
||||
}
|
||||
return $this->_clients[$domain] = $client;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $domain
|
||||
* @param $isSsl
|
||||
* @param $timeout
|
||||
* @return H2Client
|
||||
*/
|
||||
public function newRequest($domain, $isSsl, $timeout): H2Client
|
||||
{
|
||||
$domain = rtrim($domain, '/');
|
||||
if (str_contains($domain, ':')) {
|
||||
[$domain, $port] = explode(':', $domain);
|
||||
} else {
|
||||
$port = $isSsl === true ? 443 : 80;
|
||||
}
|
||||
$client = new H2Client($domain, (int)$port, $isSsl);
|
||||
$client->set(['timeout' => $timeout, 'ssl_host_name' => $domain]);
|
||||
return $client;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace HttpServer\Client;
|
||||
|
||||
|
||||
use Exception;
|
||||
use JetBrains\PhpStorm\Pure;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Snowflake;
|
||||
use Swoole\Coroutine;
|
||||
|
||||
|
||||
/**
|
||||
* Class ClientDriver
|
||||
* @package HttpServer\Client
|
||||
*/
|
||||
class HttpClient extends Component
|
||||
{
|
||||
|
||||
/**
|
||||
* @return IClient
|
||||
*/
|
||||
public static function NewRequest(): IClient
|
||||
{
|
||||
return Coroutine::getCid() > -1 ? Client::NewRequest() : Curl::NewRequest();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Http2
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function http2(): Http2
|
||||
{
|
||||
return Snowflake::app()->get('http2');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer\Client;
|
||||
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* Class HttpParse
|
||||
* @package BeReborn\Http
|
||||
*/
|
||||
class HttpParse
|
||||
{
|
||||
/**
|
||||
* @param mixed ...$object
|
||||
* @return string
|
||||
*/
|
||||
private static function getKey(...$object): string
|
||||
{
|
||||
$first = '';
|
||||
$tp = [];
|
||||
foreach ($object as $key => $value) {
|
||||
if ($value === null) {
|
||||
continue;
|
||||
}
|
||||
if (is_array($value)) {
|
||||
$value = key($value);
|
||||
}
|
||||
if ($first === '') {
|
||||
$first = $value;
|
||||
} else {
|
||||
$tp[] = $value;
|
||||
}
|
||||
}
|
||||
$key = $first . '[' . implode('][', $tp) . ']';
|
||||
if (count($tp) < 1) {
|
||||
$key = $first;
|
||||
}
|
||||
return $key;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
public static function parse($data): string
|
||||
{
|
||||
$tmp = [];
|
||||
if (is_string($data)) {
|
||||
return $data;
|
||||
}
|
||||
foreach ($data as $key => $datum) {
|
||||
if ($datum === null) {
|
||||
continue;
|
||||
}
|
||||
$tmp[] = static::ifElse($key, $datum);
|
||||
}
|
||||
return implode('&', $tmp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $t
|
||||
* @param $qt
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
private static function ifElse($t, $qt): string
|
||||
{
|
||||
if (is_numeric($qt)) {
|
||||
return $t . '=' . $qt;
|
||||
}
|
||||
if (is_string($qt)) {
|
||||
$string = $t . '=' . urlencode($qt);
|
||||
} else {
|
||||
$string = static::encode($t, $qt);
|
||||
}
|
||||
return $string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed ...$object
|
||||
* @return string
|
||||
* @throws Exception
|
||||
*/
|
||||
private static function encode(...$object): string
|
||||
{
|
||||
$ret = [];
|
||||
|
||||
$data = $object[count($object) - 1];
|
||||
$key = static::getKey(...$object);
|
||||
foreach ($data as $s => $datum) {
|
||||
if (is_array($datum)) {
|
||||
$object[count($object) - 1] = $s;
|
||||
$object[] = $datum;
|
||||
$string = static::encode(...$object);
|
||||
} else {
|
||||
if (is_object($datum)) {
|
||||
throw new Exception('Http body con\'t object.');
|
||||
}
|
||||
$string = $key . '=' . urlencode($datum);
|
||||
}
|
||||
$ret[] = $string;
|
||||
}
|
||||
return implode('&', $ret);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,217 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace HttpServer\Client;
|
||||
|
||||
|
||||
use Closure;
|
||||
|
||||
interface IClient
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|Result|int|string
|
||||
*/
|
||||
public function get(string $path, array $params = []): Result|int|array|string;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|Result|int|string
|
||||
*/
|
||||
public function post(string $path, array $params = []): Result|int|array|string;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|Result|int|string
|
||||
*/
|
||||
public function delete(string $path, array $params = []): Result|int|array|string;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|Result|int|string
|
||||
*/
|
||||
public function options(string $path, array $params = []): Result|int|array|string;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|Result|int|string
|
||||
*/
|
||||
public function upload(string $path, array $params = []): Result|int|array|string;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|Result|int|string
|
||||
*/
|
||||
public function put(string $path, array $params = []): Result|int|array|string;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|Result|int|string
|
||||
*/
|
||||
public function head(string $path, array $params = []): Result|int|array|string;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param string $path
|
||||
* @param array $params
|
||||
* @return array|Result|int|string
|
||||
*/
|
||||
public function request(string $method, string $path, array $params = []): Result|array|int|string;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $host
|
||||
* @return mixed
|
||||
*/
|
||||
public function setHost(string $host): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param array $header
|
||||
* @return mixed
|
||||
*/
|
||||
public function setHeader(array $header): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param array $header
|
||||
* @return mixed
|
||||
*/
|
||||
public function setHeaders(array $header): array;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $key
|
||||
* @param string $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function addHeader(string $key, string $value): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param int $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function setTimeout(int $value): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param Closure|null $value
|
||||
* @return mixed
|
||||
*/
|
||||
public function setCallback(?Closure $value): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $value
|
||||
* @return static
|
||||
*/
|
||||
public function setMethod(string $value): static;
|
||||
|
||||
|
||||
/**
|
||||
* @param bool $isSSL
|
||||
* @return mixed
|
||||
*/
|
||||
public function setIsSSL(bool $isSSL): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $agent
|
||||
* @return mixed
|
||||
*/
|
||||
public function setAgent(string $agent): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $errorCodeField
|
||||
* @return mixed
|
||||
*/
|
||||
public function setErrorCodeField(string $errorCodeField): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $errorMsgField
|
||||
* @return mixed
|
||||
*/
|
||||
public function setErrorMsgField(string $errorMsgField): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param bool $use_swoole
|
||||
* @return mixed
|
||||
*/
|
||||
public function setUseSwoole(bool $use_swoole): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $ssl_cert_file
|
||||
* @return mixed
|
||||
*/
|
||||
public function setSslCertFile(string $ssl_cert_file): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $ssl_key_file
|
||||
* @return mixed
|
||||
*/
|
||||
public function setSslKeyFile(string $ssl_key_file): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $ssl_key_file
|
||||
* @return mixed
|
||||
*/
|
||||
public function setCa(string $ssl_key_file): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param int $port
|
||||
* @return mixed
|
||||
*/
|
||||
public function setPort(int $port): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $message
|
||||
* @return mixed
|
||||
*/
|
||||
public function setMessage(string $message): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $data
|
||||
* @return mixed
|
||||
*/
|
||||
public function setData(string $data): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param int $connect_timeout
|
||||
* @return mixed
|
||||
*/
|
||||
public function setConnectTimeout(int $connect_timeout): void;
|
||||
|
||||
|
||||
/**
|
||||
* @param string $contentType
|
||||
* @return mixed
|
||||
*/
|
||||
public function setContentType(string $contentType): void;
|
||||
}
|
||||
@@ -1,175 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer\Client;
|
||||
|
||||
use Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Class Result
|
||||
*
|
||||
* @package app\components
|
||||
*
|
||||
* @property $code
|
||||
* @property $message
|
||||
* @property $count
|
||||
* @property $data
|
||||
*/
|
||||
class Result
|
||||
{
|
||||
public $code;
|
||||
public $message;
|
||||
public int $count = 0;
|
||||
|
||||
/** @var mixed $data */
|
||||
public $data;
|
||||
public ?array $header;
|
||||
public int $httpStatus = 200;
|
||||
|
||||
public int $startTime = 0;
|
||||
public int $requestTime = 0;
|
||||
public float $runTime = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Result constructor.
|
||||
* @param array $data
|
||||
*/
|
||||
public function __construct(array $data)
|
||||
{
|
||||
$this->setAssignment($data);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $data
|
||||
* @return $this
|
||||
*/
|
||||
public function setAssignment($data): static
|
||||
{
|
||||
foreach ($data as $key => $val) {
|
||||
if (!property_exists($this, $key)) {
|
||||
continue;
|
||||
}
|
||||
$this->$key = $val;
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name): mixed
|
||||
{
|
||||
return $this->$name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @param $value
|
||||
*/
|
||||
public function __set($name, $value)
|
||||
{
|
||||
$this->$name = $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getHeaders(): array
|
||||
{
|
||||
$_tmp = [];
|
||||
if (!is_array($this->header)) {
|
||||
return $_tmp;
|
||||
}
|
||||
foreach ($this->header as $key => $val) {
|
||||
if ($key == 0) {
|
||||
$_tmp['pro'] = $val;
|
||||
} else {
|
||||
if (str_contains($val, ': ')) {
|
||||
$trim = explode(': ', $val);
|
||||
|
||||
$_tmp[strtolower($trim[0])] = $trim[1];
|
||||
} else {
|
||||
$_tmp[$key] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $_tmp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getTime(): array
|
||||
{
|
||||
return [
|
||||
'startTime' => $this->startTime,
|
||||
'requestTime' => $this->requestTime,
|
||||
'runTime' => $this->runTime,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param $key
|
||||
* @param $data
|
||||
* @return $this
|
||||
* @throws Exception
|
||||
*/
|
||||
public function setAttr($key, $data): static
|
||||
{
|
||||
if (!property_exists($this, $key)) {
|
||||
throw new Exception('未查找到相应对象属性');
|
||||
}
|
||||
$this->$key = $data;
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $status
|
||||
* @return bool
|
||||
*/
|
||||
public function isResultsOK($status = 0): bool
|
||||
{
|
||||
if (!$this->httpIsOk()) {
|
||||
return false;
|
||||
}
|
||||
return $this->code === $status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function httpIsOk(): bool
|
||||
{
|
||||
return in_array($this->httpStatus, [100, 101, 200, 201, 202, 203, 204, 205, 206]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getBody(): mixed
|
||||
{
|
||||
return $this->data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getMessage(): mixed
|
||||
{
|
||||
return $this->message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed
|
||||
*/
|
||||
public function getCode(): mixed
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Input;
|
||||
use Snowflake\Exception\ConfigException;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class Command
|
||||
* @package HttpServer
|
||||
*/
|
||||
class Command extends \Console\Command
|
||||
{
|
||||
|
||||
public string $command = 'sw:server';
|
||||
|
||||
|
||||
public string $description = 'server start|stop|reload|restart';
|
||||
|
||||
|
||||
const ACTIONS = ['start', 'stop', 'restart'];
|
||||
|
||||
|
||||
/**
|
||||
* @param Input $dtl
|
||||
* @return string
|
||||
* @throws Exception
|
||||
* @throws ConfigException
|
||||
*/
|
||||
public function onHandler(Input $dtl): string
|
||||
{
|
||||
$manager = Snowflake::app()->getServer();
|
||||
$manager->setDaemon($dtl->get('daemon', 0));
|
||||
|
||||
if (!in_array($dtl->get('action'), self::ACTIONS)) {
|
||||
return 'I don\'t know what I want to do.';
|
||||
}
|
||||
|
||||
/** @var Shutdown $shutdown */
|
||||
$shutdown = Snowflake::app()->get('shutdown');
|
||||
if ($shutdown->isRunning() && $dtl->get('action') == 'start') {
|
||||
return 'Service is running. Please use restart.';
|
||||
}
|
||||
|
||||
$shutdown->shutdown();
|
||||
if ($dtl->get('action') == 'stop') {
|
||||
return 'shutdown success.';
|
||||
}
|
||||
|
||||
$this->generate_runtime_builder();
|
||||
|
||||
return $manager->start();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private function generate_runtime_builder()
|
||||
{
|
||||
exec(PHP_BINARY . ' ' . APP_PATH . 'snowflake runtime:builder');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer;
|
||||
|
||||
|
||||
use Exception;
|
||||
use HttpServer\Abstracts\HttpService;
|
||||
use HttpServer\Http\HttpHeaders;
|
||||
use HttpServer\Http\HttpParams;
|
||||
use HttpServer\Http\Request;
|
||||
use Snowflake\Abstracts\TraitApplication;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
/**
|
||||
* Class WebController
|
||||
* @package Snowflake\Snowflake\Web
|
||||
* @property-read HttpParams $input
|
||||
* @property-read HttpHeaders $headers
|
||||
* @property-read Request $request
|
||||
*/
|
||||
class Controller extends HttpService
|
||||
{
|
||||
|
||||
use TraitApplication;
|
||||
|
||||
|
||||
/**
|
||||
* Controller constructor.
|
||||
* @param array $config
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __construct($config = [])
|
||||
{
|
||||
parent::__construct($config);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @throws Exception
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$annotation = Snowflake::getAnnotation();
|
||||
$annotation->injectProperty($this);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return ?HttpParams
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getInput(): ?HttpParams
|
||||
{
|
||||
return \request()->params;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ?HttpHeaders
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getHeaders(): ?HttpHeaders
|
||||
{
|
||||
return \request()->headers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Request|null
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getRequest(): ?Request
|
||||
{
|
||||
return \request();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $name
|
||||
* @return mixed
|
||||
* @throws Exception
|
||||
*/
|
||||
public function __get($name): mixed
|
||||
{
|
||||
// TODO: Change the autogenerated stub
|
||||
if (property_exists($this, $name)) {
|
||||
return $this->$name;
|
||||
}
|
||||
|
||||
$method = 'get' . ucfirst($name);
|
||||
if (method_exists($this, $method)) {
|
||||
return $this->{$method}();
|
||||
}
|
||||
|
||||
return Snowflake::app()->get($name);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
<?php
|
||||
|
||||
|
||||
namespace HttpServer;
|
||||
|
||||
|
||||
use Exception;
|
||||
use Snowflake\Abstracts\Component;
|
||||
use Snowflake\Snowflake;
|
||||
|
||||
|
||||
/**
|
||||
* Class Emit
|
||||
* @package HttpServer
|
||||
*/
|
||||
class Emit extends Component
|
||||
{
|
||||
|
||||
private array $_array = [];
|
||||
|
||||
|
||||
/**
|
||||
* @param int[] $users
|
||||
* @param string $message
|
||||
* @throws Exception
|
||||
*/
|
||||
public function emit(array $users, string $message)
|
||||
{
|
||||
$table = Snowflake::app()->getTable('SYSTEM:ONLINE:PEOPLES');
|
||||
|
||||
foreach ($users as $user) {
|
||||
$fd = $table->get((string)$user, ['clientId']);
|
||||
|
||||
Snowflake::push($fd, $message);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer\Events;
|
||||
|
||||
|
||||
use Exception;
|
||||
use HttpServer\Abstracts\Callback;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Exception\ComponentException;
|
||||
use Snowflake\Snowflake;
|
||||
use Swoole\Server;
|
||||
|
||||
/**
|
||||
* Class OnAfterReload
|
||||
* @package HttpServer\Events
|
||||
*/
|
||||
class OnAfterReload extends Callback
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onHandler(Server $server)
|
||||
{
|
||||
Event::trigger(Event::SERVER_AFTER_RELOAD, [$server]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer\Events;
|
||||
|
||||
|
||||
use Exception;
|
||||
use HttpServer\Abstracts\Callback;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Snowflake;
|
||||
use Swoole\Server;
|
||||
use Swoole\Timer;
|
||||
|
||||
/**
|
||||
* Class OnBeforeReload
|
||||
* @package HttpServer\Events
|
||||
*/
|
||||
class OnBeforeReload extends Callback
|
||||
{
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onHandler(Server $server)
|
||||
{
|
||||
Event::trigger(Event::SERVER_BEFORE_RELOAD, [$server]);
|
||||
|
||||
Snowflake::clearWorkerPid();
|
||||
Snowflake::clearTaskPid();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer\Events;
|
||||
|
||||
|
||||
use Exception;
|
||||
use HttpServer\Abstracts\Callback;
|
||||
use Snowflake\Event;
|
||||
use Swoole\Server;
|
||||
|
||||
/**
|
||||
* Class OnClose
|
||||
* @package HttpServer\Events
|
||||
*
|
||||
*/
|
||||
class OnClose extends Callback
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $fd
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onHandler(Server $server, int $fd)
|
||||
{
|
||||
try {
|
||||
defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES));
|
||||
|
||||
Event::trigger(Event::SERVER_CLIENT_CLOSE, [$server, $fd]);
|
||||
} catch (\Throwable $exception) {
|
||||
$this->addError($exception, 'throwable');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer\Events;
|
||||
|
||||
|
||||
use Exception;
|
||||
use HttpServer\Abstracts\Callback;
|
||||
use Snowflake\Event;
|
||||
use Swoole\Server;
|
||||
|
||||
/**
|
||||
* Class OnConnect
|
||||
* @package HttpServer\Events
|
||||
*/
|
||||
class OnConnect extends Callback
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param int $fd
|
||||
* @param int $reactorId
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onHandler(Server $server, int $fd, int $reactorId)
|
||||
{
|
||||
try {
|
||||
defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES));
|
||||
if (($clientInfo = $server->getClientInfo($fd, $reactorId)) === false) {
|
||||
return;
|
||||
}
|
||||
if (isset($clientInfo['websocket_status'])) {
|
||||
return;
|
||||
}
|
||||
fire($this->getName($clientInfo, Event::SERVER_CONNECT), [$server, $fd, $reactorId]);
|
||||
} catch (\Throwable $throwable) {
|
||||
$this->addError($throwable, 'connect');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer\Events;
|
||||
|
||||
|
||||
use Exception;
|
||||
use HttpServer\Abstracts\Callback;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Snowflake;
|
||||
use Swoole\Server;
|
||||
|
||||
/**
|
||||
* Class OnFinish
|
||||
* @package HttpServer\Events
|
||||
*/
|
||||
class OnFinish extends Callback
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param Server $server
|
||||
* @param $task_id
|
||||
* @param $data
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onHandler(Server $server, $task_id, $data)
|
||||
{
|
||||
try {
|
||||
defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES));
|
||||
|
||||
fire(Event::TASK_FINISH, [$task_id, $data]);
|
||||
} catch (\Throwable $exception) {
|
||||
$this->addError($exception, 'task');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace HttpServer\Events;
|
||||
|
||||
|
||||
use Annotation\Route\Socket;
|
||||
use Exception;
|
||||
use HttpServer\Abstracts\Callback;
|
||||
use HttpServer\Http\HttpHeaders;
|
||||
use HttpServer\Http\HttpParams;
|
||||
use HttpServer\Http\Request;
|
||||
use HttpServer\Http\Response;
|
||||
use HttpServer\Route\Router;
|
||||
use ReflectionException;
|
||||
use Snowflake\Core\ArrayAccess;
|
||||
use Snowflake\Event;
|
||||
use Snowflake\Exception\NotFindClassException;
|
||||
use Snowflake\Snowflake;
|
||||
use Swoole\Http\Request as SRequest;
|
||||
use Swoole\Http\Response as SResponse;
|
||||
use Swoole\WebSocket\Server;
|
||||
|
||||
|
||||
/**
|
||||
* Class OnHandshake
|
||||
* @package HttpServer\Events
|
||||
*/
|
||||
class OnHandshake extends Callback
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* @param $request
|
||||
* @param $response
|
||||
* @return Router
|
||||
* @throws Exception
|
||||
*/
|
||||
private function _protocol($request, $response): Router
|
||||
{
|
||||
/** @var Server $server */
|
||||
$secWebSocketKey = $request->header['sec-websocket-key'];
|
||||
$patten = '#^[+/0-9A-Za-z]{21}[AQgw]==$#';
|
||||
if (0 === preg_match($patten, $secWebSocketKey) || 16 !== strlen(base64_decode($secWebSocketKey))) {
|
||||
throw new Exception('protocol error.', 500);
|
||||
}
|
||||
$key = base64_encode(sha1($request->header['sec-websocket-key'] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', TRUE));
|
||||
$headers = [
|
||||
'Upgrade' => 'websocket',
|
||||
'Connection' => 'Upgrade',
|
||||
'Sec-websocket-Accept' => $key,
|
||||
'Sec-websocket-Version' => '13',
|
||||
];
|
||||
if (isset($request->header['sec-websocket-protocol'])) {
|
||||
$headers['Sec-websocket-Protocol'] = $request->header['sec-websocket-protocol'];
|
||||
}
|
||||
foreach ($headers as $key => $val) {
|
||||
$response->header($key, $val);
|
||||
}
|
||||
return Snowflake::app()->getRouter();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param SResponse $response
|
||||
* @param int $code
|
||||
* @return void
|
||||
*/
|
||||
private function disconnect(SResponse $response, int $code = 500): void
|
||||
{
|
||||
$server = Snowflake::getWebSocket();
|
||||
if (!$server->isEstablished($response->fd)) {
|
||||
return;
|
||||
}
|
||||
$response->status($code);
|
||||
$response->end();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param SRequest $request
|
||||
* @param SResponse $response
|
||||
* @return void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function onHandler(SRequest $request, SResponse $response): void
|
||||
{
|
||||
try {
|
||||
defer(fn() => fire(Event::SYSTEM_RESOURCE_RELEASES));
|
||||
|
||||
$router = $this->_protocol($request, $response);
|
||||
|
||||
[$sRequest, $sResponse] = $this->sRequest($request, $response);
|
||||
|
||||
if (($node = $router->find_path($sRequest)) !== null) {
|
||||
$node->dispatch($sRequest, $sResponse);
|
||||
} else {
|
||||
$this->disconnect($response, 404);
|
||||
}
|
||||
} catch (\Throwable $exception) {
|
||||
$this->addError($exception, 'throwable');
|
||||
$response->status(500);
|
||||
$response->end($exception->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param $request
|
||||
* @param SResponse $response
|
||||
* @return array
|
||||
* @throws NotFindClassException
|
||||
* @throws ReflectionException
|
||||
* @throws Exception
|
||||
*/
|
||||
private function sRequest($request, SResponse $response): array
|
||||
{
|
||||
/** @var Request $sRequest */
|
||||
$sRequest = Request::create($request);
|
||||
$sRequest->uri = '/' . Socket::HANDSHAKE . '::event';
|
||||
|
||||
$sRequest->headers = new HttpHeaders(ArrayAccess::merge($request->server, $request->header));
|
||||
|
||||
$sRequest->headers->replace('request_method', 'sw::socket');
|
||||
$sRequest->headers->replace('request_uri', $sRequest->uri);
|
||||
|
||||
$sRequest->params = new HttpParams([], $request->get, []);
|
||||
|
||||
$sRequest->parseUri();
|
||||
|
||||
return [$sRequest, Response::create($response)];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user