Compare commits
658 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 10a4eb3ddc | |||
| 51f46cf871 | |||
| 697548d1c7 | |||
| f717628322 | |||
| e91b297cc2 | |||
| c92441e544 | |||
| f0573fc68c | |||
| eb44480fdf | |||
| 1ad05fbfc9 | |||
| 673e24a2ea | |||
| 4842be01cd | |||
| dddb38d4ee | |||
| 727ce0f795 | |||
| ba27acead9 | |||
| a026a81a8a | |||
| 5e7ee0c236 | |||
| bb30d5ebd2 | |||
| 2ae3b09b8c | |||
| 473d76f1b7 | |||
| 918e454c42 | |||
| 7e32fdb682 | |||
| 171a472966 | |||
| 8194655ad1 | |||
| 80c1812bc8 | |||
| 6c37b33509 | |||
| 509bcee540 | |||
| 3dec881848 | |||
| 65b522a0a0 | |||
| 9164567abe | |||
| 12314f16a2 | |||
| 1621d01992 | |||
| ae05bfd350 | |||
| 79567d4e8f | |||
| 334a56ce5c | |||
| c2ee3303a5 | |||
| bfc89a7247 | |||
| 326309e61e | |||
| 8926e8c7d9 | |||
| ee7ee81098 | |||
| f4b707e928 | |||
| c38030def2 | |||
| 43a61d8a06 | |||
| 4fd3725c51 | |||
| 949861a890 | |||
| 122069752a | |||
| c288734877 | |||
| 4b22ff3a75 | |||
| 2b1a43b40a | |||
| 076d90ddc4 | |||
| 1e2e26d898 | |||
| f56cb2c3ac | |||
| ae83b0fbaf | |||
| fb7b65cf3b | |||
| 168abddacf | |||
| 99e91a1053 | |||
| bad118ac6b | |||
| f334c3d74a | |||
| 0e6c199a7e | |||
| 0bc39afdab | |||
| cf3de52249 | |||
| 3f0569af41 | |||
| 9f078357a7 | |||
| bb837232ba | |||
| 6d57afc71a | |||
| fd682efdb1 | |||
| 5c614a88a2 | |||
| f27a0c0461 | |||
| 3ef9635406 | |||
| c527833081 | |||
| 5caf091406 | |||
| 5a29441640 | |||
| 75a42fd0d6 | |||
| 84da5f43a2 | |||
| 0da7ed8d93 | |||
| 0aa72e5026 | |||
| 14cfd2a8df | |||
| d6b3d115b0 | |||
| 7b1fd5378f | |||
| 9e9b94b1d5 | |||
| cf837d783d | |||
| 3df44e2990 | |||
| 0c5ebb2674 | |||
| ba2fa2bff4 | |||
| 03090e85fd | |||
| 5c55d6a6e3 | |||
| 0632d73e32 | |||
| 000c2637d6 | |||
| bf24e101d3 | |||
| 08c837602f | |||
| 563867cd8b | |||
| 86c66511dd | |||
| eedd109332 | |||
| 7d57521ad8 | |||
| d5fc18dc95 | |||
| e36b3d46e8 | |||
| d8aa98e60c | |||
| 8a8899397e | |||
| dc69b5a825 | |||
| df7691ada3 | |||
| 1048df7e63 | |||
| 457560920d | |||
| e79c0ae2b5 | |||
| e74e8f9d73 | |||
| 23b0c89848 | |||
| 285989e737 | |||
| 2c580d0b20 | |||
| 3c1f6abd0d | |||
| 4eb1ef3444 | |||
| 0f503fc320 | |||
| aebc30c7a3 | |||
| 44bc365fdd | |||
| 06defee410 | |||
| d5d4dc9561 | |||
| be2c72f8b4 | |||
| 62f46d531f | |||
| 6bfdbe3e8a | |||
| 7095b21eb4 | |||
| efce912332 | |||
| b33a265ea4 | |||
| db849c1e36 | |||
| b01721c2a9 | |||
| 4f2a807327 | |||
| 955573256d | |||
| d963f5cd7d | |||
| 2467b5ee3b | |||
| f86eb4b741 | |||
| 33b99073f0 | |||
| 880636c5a6 | |||
| 6e344f335e | |||
| 6b205bd725 | |||
| d97a0f5b6c | |||
| a510396a57 | |||
| 297d54ec98 | |||
| 531306a091 | |||
| 4346f73159 | |||
| 3cb5754ff2 | |||
| bf5bb8bc70 | |||
| 7b7ad4d350 | |||
| 544a0756f3 | |||
| 934215307d | |||
| 349825b4f8 | |||
| f3f1a161e4 | |||
| c088187a13 | |||
| 4db6ce4b22 | |||
| 72a366d0dc | |||
| fc18189fc8 | |||
| 49cfeee5b0 | |||
| 01d09548aa | |||
| 1ff049a063 | |||
| 7c720460f5 | |||
| d0c0ec56a4 | |||
| 3c965e8c32 | |||
| 5bcd6a9982 | |||
| 525477f84f | |||
| 7d051dffbb | |||
| c5a7eab1d5 | |||
| 115c8b15fd | |||
| 29c8f065f7 | |||
| 961755336a | |||
| e0aff8a1e4 | |||
| 6fa0c627a5 | |||
| b3c2574aac | |||
| 98b2320421 | |||
| 66a63b3cbb | |||
| 077f3468b9 | |||
| 21c5b6fe02 | |||
| 3274d873a9 | |||
| ffed85640d | |||
| 250f082346 | |||
| cdbf89ee57 | |||
| 056b13eb98 | |||
| e2a395e245 | |||
| 6b760dcfe8 | |||
| 5ded732188 | |||
| 9467a67661 | |||
| d6a83d9887 | |||
| 96e00bc1eb | |||
| 0f9f11bbcf | |||
| 5b6cc51516 | |||
| 80b83ab64b | |||
| 326d81286a | |||
| 13641473d0 | |||
| c6751f0374 | |||
| d71c686aea | |||
| 4c5dfb42d5 | |||
| 0245efe3cb | |||
| b3151ca788 | |||
| aa1edb6e69 | |||
| 0b4ddf82aa | |||
| 3ff173732b | |||
| f3f7aa70d1 | |||
| cd82bc6d21 | |||
| c3a6c7c473 | |||
| 5538a2e793 | |||
| 1b7dc76df2 | |||
| 85c85cd1eb | |||
| ba5f2bc69d | |||
| 3fcdbe85b5 | |||
| 78336181ea | |||
| 17883358b6 | |||
| fc0c6a1cd8 | |||
| 934d4020b2 | |||
| 8b03ba4f42 | |||
| 3caf84c63c | |||
| aae16f227e | |||
| 443002cdde | |||
| 75150f0bfa | |||
| af73fd8b68 | |||
| 139df63ddf | |||
| a49058fe00 | |||
| dcde00cec1 | |||
| bcc70f7a1e | |||
| 32bc2f1d69 | |||
| 4d3f67885a | |||
| a269e9d426 | |||
| af5a382f93 | |||
| 90174a39e3 | |||
| 4d9f9c890d | |||
| dad910b8ab | |||
| 8a70c440f2 | |||
| 07f3de8b67 | |||
| 0955b0c474 | |||
| 57d1ff20fd | |||
| fbdb1d5d6c | |||
| b924b06062 | |||
| fb029861cf | |||
| 4eb19bd26c | |||
| 71a07060a9 | |||
| edaa5ebd43 | |||
| c12b270511 | |||
| c8fa2b3880 | |||
| d474481cba | |||
| 62e3ab27fe | |||
| 86c008fc8c | |||
| 154ee39755 | |||
| 63ca9f210b | |||
| 1c139b685a | |||
| 7a8b3dc9bc | |||
| a4dde1948f | |||
| 0f68818a19 | |||
| 414b65b269 | |||
| 28c2aa1195 | |||
| 391c778b80 | |||
| f2c2b7590b | |||
| 22d6981ab0 | |||
| 4dbe317c03 | |||
| dc727ba0de | |||
| 2dd04799b2 | |||
| 1c901e00cc | |||
| d7207f7c2a | |||
| a5828a2c3e | |||
| c589c741e8 | |||
| c8923cbc27 | |||
| 063f405a06 | |||
| 68a25bb5b1 | |||
| addfbcf2a7 | |||
| 8ee133bb75 | |||
| fa1185cbd8 | |||
| 68e0a414a0 | |||
| 6ddef7df27 | |||
| 66f572b642 | |||
| a7a1730898 | |||
| 155e7338cf | |||
| 89860bd786 | |||
| b5cfefa052 | |||
| b2c0f3c35a | |||
| d5e0c6ff68 | |||
| a43f4b7b7f | |||
| 7ce3949852 | |||
| 4862419744 | |||
| 6b810c89f6 | |||
| 89b0a2fd89 | |||
| 73c479c843 | |||
| 8aceae9880 | |||
| 384d4d60f1 | |||
| 67caf81a74 | |||
| 763ab26446 | |||
| 67a8fa5f07 | |||
| f7b61d09e2 | |||
| 5c59317bf8 | |||
| a2ec53dd4f | |||
| db78c78df2 | |||
| 4558549d5a | |||
| d98801d5d1 | |||
| de9ecf6afc | |||
| 702790bf77 | |||
| 3a1dbc778b | |||
| c912e80134 | |||
| 098c856138 | |||
| b45306e1ff | |||
| 3499f39970 | |||
| 4fb61be092 | |||
| 9115aa1a6d | |||
| f98b81116c | |||
| 904cbbb906 | |||
| c0380e491b | |||
| 8656d3e4b9 | |||
| 40988b4655 | |||
| 8a8b69a442 | |||
| 06dbea84d8 | |||
| f54cf32057 | |||
| 64dbf0207b | |||
| f743830167 | |||
| 206c88105e | |||
| 3177b979d3 | |||
| 0addd719d3 | |||
| 662dfb37d3 | |||
| 4ab32dd270 | |||
| fec55e9d1c | |||
| a21aa079ff | |||
| ef4246478d | |||
| dda538d1fc | |||
| 137d859532 | |||
| d6d80ae037 | |||
| 82b2821e27 | |||
| b270cefacc | |||
| 8b064fc2ec | |||
| b4e984fe6a | |||
| 1a3339d485 | |||
| f62e4fa973 | |||
| ee8050f38f | |||
| 8cb0f5762c | |||
| 287596220a | |||
| f870ee18d4 | |||
| b506b5c8e9 | |||
| d9e843f0ba | |||
| 805c1dfb5b | |||
| 66dd0d073c | |||
| f269b1931d | |||
| 29c22cc4b5 | |||
| 76695fc7b2 | |||
| e29031a2c4 | |||
| 9b2b8e8166 | |||
| 3ff0cca033 | |||
| aa398b4f36 | |||
| fe16cc91fa | |||
| 7e6fdcb05e | |||
| ae54f34bcf | |||
| d1e071b9cb | |||
| 3e253f9c19 | |||
| 2ce952bdbb | |||
| b8f5d1c42c | |||
| 6a9b8d5540 | |||
| fdc9261399 | |||
| 64b247157c | |||
| fcacc1bd71 | |||
| 68d581ac82 | |||
| af86a5d7b1 | |||
| 0f25029ff6 | |||
| 060e584503 | |||
| 743c0bb31c | |||
| 4bac3e19fe | |||
| b86cddda94 | |||
| 11103c0bc5 | |||
| 8210702474 | |||
| a42b660648 | |||
| f11d4fbedd | |||
| 9105c08a4c | |||
| 71b3ea2e56 | |||
| 33b3032b30 | |||
| 31e5ed7b1b | |||
| 98c8d637f4 | |||
| 8a3eae9ea6 | |||
| 5aec753859 | |||
| eeaa9166ac | |||
| 751ace1168 | |||
| 51da5343ea | |||
| 34df5009e0 | |||
| d4db7d9523 | |||
| 6a5a320a22 | |||
| 62cf1cd87d | |||
| ebf22d155e | |||
| 01644e8f6c | |||
| f2be1669bf | |||
| e17b5e6a7b | |||
| 24911bffe2 | |||
| d343340f56 | |||
| 0c82f78c43 | |||
| 5cf3a619f7 | |||
| 49550b410a | |||
| b9df55ef98 | |||
| e456c44b46 | |||
| 61315a8d83 | |||
| a1c65f0518 | |||
| 49c8313c9e | |||
| 141f9b6ea1 | |||
| d223ee97cd | |||
| a098e49840 | |||
| 8785239964 | |||
| 74a691ac3a | |||
| 38c1669e57 | |||
| 58f0d1a464 | |||
| f30740bd49 | |||
| 3de3ccad00 | |||
| 75502ca18c | |||
| c531c36cab | |||
| 387e64acac | |||
| 91a5d55183 | |||
| 9819318060 | |||
| 2e990a7869 | |||
| ed7175192b | |||
| 4e63bb38f3 | |||
| d61b9bfdd7 | |||
| 0de53308f5 | |||
| 85bf47df82 | |||
| 791c3f5208 | |||
| bc7876681b | |||
| 68aa3f7b1b | |||
| 976531fe7e | |||
| ded7350d74 | |||
| e3594bf6fc | |||
| 6a6d9ec7b0 | |||
| 200a400fc5 | |||
| 76c807a4e7 | |||
| 985db6d2e3 | |||
| 7894fcfc91 | |||
| f41b0ff4b5 | |||
| d0a5892f9f | |||
| c0f4950270 | |||
| 1d9c3b1a79 | |||
| c5047148b3 | |||
| a6b3233c10 | |||
| 9ec1f9b3f9 | |||
| ed2126eef9 | |||
| ce4b56895e | |||
| eaac76cdc1 | |||
| bffe52e060 | |||
| 94db371234 | |||
| b12cd81c01 | |||
| 103e226b51 | |||
| 208cf8a01d | |||
| 1f81107485 | |||
| bf5042e3d0 | |||
| 15b55f2b36 | |||
| 57f2250f13 | |||
| f15682ef60 | |||
| 1b1ec04e7c | |||
| 049c65a2c7 | |||
| d50aa38c31 | |||
| 1531f979a2 | |||
| 69ffecd686 | |||
| 6ec297aaaf | |||
| bb1edd2051 | |||
| 14790559cb | |||
| 97457087c7 | |||
| 8469d18a0e | |||
| da3269e970 | |||
| b2b0afde4b | |||
| ff849ab912 | |||
| 97b8a5000a | |||
| f59489a5cb | |||
| b03427cabc | |||
| 2eb5c08825 | |||
| 37eb66510f | |||
| dc7c7304ad | |||
| 8327b8aa0e | |||
| 7759249963 | |||
| 9d9070c979 | |||
| feb1a14650 | |||
| 4cb4ff0617 | |||
| 9e1d6dbf9b | |||
| 82ec2d28ef | |||
| 66383c6f16 | |||
| dc60eb8383 | |||
| 9733c5c031 | |||
| 0c0c08ec98 | |||
| d7d800331b | |||
| 4346578160 | |||
| cfe0b2f9e5 | |||
| d7d7d88ecc | |||
| fd34a9cd29 | |||
| 3f1b057f45 | |||
| 6da1a5adb3 | |||
| 23cf5b544a | |||
| b0cde715da | |||
| 366ca11490 | |||
| a1a985e4a8 | |||
| 3384634033 | |||
| b6bcdcb351 | |||
| db5b99dbf1 | |||
| a64dbb172e | |||
| b1913c9a07 | |||
| 11fc06d75d | |||
| f6179ff813 | |||
| 186e664894 | |||
| 1735c5adca | |||
| 31e715e146 | |||
| 4a7f7813e7 | |||
| 5f50bae65c | |||
| 996d74b1d3 | |||
| e6d8a83519 | |||
| d3aa1b3d7e | |||
| 3effe6b96d | |||
| 0b2428e9a3 | |||
| 6458c223b8 | |||
| d36fc65baa | |||
| a511c84b4d | |||
| ff34024f39 | |||
| bdc0ae7e2f | |||
| 60965ecd92 | |||
| 708b49ca13 | |||
| b6baa9af3d | |||
| 8c7db9e846 | |||
| 176ec0edc0 | |||
| 0d1cf872d3 | |||
| 13b6318ad2 | |||
| 18352f8a4d | |||
| ad52b86336 | |||
| 38df2017de | |||
| 210f66cc4a | |||
| e7e209280c | |||
| 5b7e9c712e | |||
| 33aa4e2062 | |||
| 1efa75c891 | |||
| f48fb5c499 | |||
| cb13b4a0e0 | |||
| cb8dbf9da5 | |||
| 2a05687c8b | |||
| d4514844f8 | |||
| 6b7a495d19 | |||
| 601eb0bf38 | |||
| 037e7e0797 | |||
| a7e32e97e3 | |||
| 9d90506265 | |||
| 08100793af | |||
| a265424b3f | |||
| bb87fa7fa8 | |||
| 16cf64866a | |||
| 11da6d5be7 | |||
| ea35ea1af5 | |||
| 33c32579c8 | |||
| 1ac6f6db50 | |||
| cacf87be2d | |||
| 7baa81c2df | |||
| a0e88a297d | |||
| 8d2b52a5b0 | |||
| 81389ce435 | |||
| e981776e6d | |||
| 48b3806129 | |||
| 9fc8e18881 | |||
| 250276bbd4 | |||
| af29f61478 | |||
| cdfebe705d | |||
| e6714ae829 | |||
| a0dead872b | |||
| b6ebc34199 | |||
| 49e7ace2d9 | |||
| d140eab12d | |||
| 24fcfd9fcb | |||
| 83e05a4f84 | |||
| 48dd619899 | |||
| ff52755636 | |||
| a7cd18c3d2 | |||
| 98a0208b47 | |||
| b923305527 | |||
| 04ccbdde4d | |||
| de1e3d150f | |||
| 07182529f4 | |||
| e076b687c6 | |||
| 7f305db637 | |||
| 50e10155e7 | |||
| 478b7cde42 | |||
| c86f52d5ea | |||
| 58fc51ae93 | |||
| 413248a126 | |||
| f114f94740 | |||
| ce162e2657 | |||
| 00518f8451 | |||
| ba3c1f9d21 | |||
| 7535585b63 | |||
| bf288c0502 | |||
| f8375857c2 | |||
| 2391ee1368 | |||
| 327d17c90e | |||
| d6b4c47cd9 | |||
| a052fc42b1 | |||
| c89fb0a0be | |||
| 03a606432a | |||
| 54e826bc96 | |||
| 6c57222a2e | |||
| 97e8573dff | |||
| 683862932b | |||
| 9a856df8bc | |||
| e1ef2e8700 | |||
| 59599efab6 | |||
| 20813ef207 | |||
| 99e0a1f11b | |||
| 9bf2819ac6 | |||
| cafeb6d8c6 | |||
| d04f2a98b9 | |||
| f41f82adc5 | |||
| e6ae88c016 | |||
| 474dcd0754 | |||
| 369f6ac935 | |||
| 5a928aa459 | |||
| 416a9ed064 | |||
| b13c3aa3b9 | |||
| 99ae94a82f | |||
| 997e0e5492 | |||
| 376fe0bf55 | |||
| 282da69d61 | |||
| c83844468d | |||
| 80b5cfbb07 | |||
| aacb86bf92 | |||
| 59391f58ec | |||
| 0debf9c34f | |||
| 9fa17ef6cb | |||
| d227aa19b8 | |||
| e0a10080b1 | |||
| 807df434f6 | |||
| d963917556 | |||
| 347d41c841 | |||
| f16aa38fff | |||
| 62a7e0acd0 | |||
| 8e89d13142 | |||
| a5782a40af | |||
| c6af319805 | |||
| 516beedbbb | |||
| 7cd01fc50b | |||
| e9d12ae0d8 | |||
| 02e167c1f6 | |||
| baed01518c | |||
| a0106ff811 | |||
| e0da5a9cb2 | |||
| 451d5eb484 | |||
| 1923b68594 | |||
| 3abd4df8bd | |||
| ea239e6122 | |||
| 3fe99a402e | |||
| e738738e54 | |||
| f502912225 | |||
| c8a26bf6a3 | |||
| e06e50c4fc | |||
| 4236473b14 | |||
| 3285e161c0 | |||
| b5c3fb1728 | |||
| e1caf3a470 | |||
| b6cf182341 | |||
| c74cdb28d6 | |||
| b200cb463e | |||
| cdf5ddf539 | |||
| 5716edcf80 | |||
| 0fe33c120b | |||
| 10ea234dbf | |||
| 31f146fc6f | |||
| 0af73b0290 | |||
| 6675bac1dc | |||
| 0d49a59cfe | |||
| baa22301e9 | |||
| fdfb6187e9 | |||
| 69830f28c2 | |||
| e65a71a05a | |||
| 7a2a444579 | |||
| e16ebecda4 | |||
| 0218e39664 | |||
| 7e645f9a6a | |||
| fe23502e67 | |||
| ad2764e3ac |
@@ -106,3 +106,4 @@ src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
|
||||
src/Umbraco.Web.UI/[Cc]onfig/appSettings.config
|
||||
src/Umbraco.Web.UI/[Cc]onfig/connectionStrings.config
|
||||
src/Umbraco.Web.UI/umbraco/plugins/*
|
||||
src/Umbraco.Web.UI/umbraco/js/init.js
|
||||
|
||||
@@ -1,7 +1,11 @@
|
||||
Umbraco CMS
|
||||
===========
|
||||
##Note: Building version 7 from source##
|
||||
If you're interested in using the source code and building version 7, make sure to read the [Belle ReadMe file](src/Umbraco.Web.UI.Client/README.md). Note that you can always [download a nightly build](http://nightly.umbraco.org/umbraco%207.0.0/) so you don't have to build the code yourself.
|
||||
Umbraco is a free open source Content Management System built on the ASP.NET platform.
|
||||
|
||||
## Building Umbraco from source ##
|
||||
The easiest way to get started is to run `build/build.bat` which will build both the backoffice (also known as "Belle") and the Umbraco core. You can then easily start debugging from Visual Studio, or if you need to debug Belle you can run `grunt dev` in `src\Umbraco.Web.UI.Client`.
|
||||
|
||||
If you're interested in making changes to Belle make sure to read the [Belle ReadMe file](src/Umbraco.Web.UI.Client/README.md). Note that you can always [download a nightly build](http://nightly.umbraco.org/umbraco%207.0.0/) so you don't have to build the code yourself.
|
||||
|
||||
## Watch a five minute introduction video ##
|
||||
|
||||
|
||||
+10
-1
@@ -1,14 +1,21 @@
|
||||
@ECHO OFF
|
||||
SET release=7.0.0
|
||||
SET release=7.0.2
|
||||
SET comment=
|
||||
SET version=%release%
|
||||
|
||||
IF [%comment%] EQU [] (SET version=%release%) ELSE (SET version=%release%-%comment%)
|
||||
ECHO Building Umbraco %version%
|
||||
|
||||
ReplaceIISExpressPortNumber.exe ..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj %release%
|
||||
|
||||
ECHO Installing the Microsoft.Bcl.Build package before anything else, otherwise you'd have to run build.cmd twice
|
||||
SET nuGetFolder=%CD%\..\src\packages\
|
||||
..\src\.nuget\NuGet.exe install ..\src\Umbraco.Web.UI\packages.config -OutputDirectory %nuGetFolder%
|
||||
|
||||
ECHO Performing MSBuild and producing Umbraco binaries zip files
|
||||
%windir%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe "Build.proj" /p:BUILD_RELEASE=%release% /p:BUILD_COMMENT=%comment%
|
||||
|
||||
ECHO Adding dummy files to include in the NuGet package so that empty folders actually get created
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\App_Code\dummy.txt
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\App_Data\dummy.txt
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\App_Plugins\dummy.txt
|
||||
@@ -20,9 +27,11 @@ echo This file is only here so that the containing folder will be included in th
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\Views\Partials\dummy.txt
|
||||
echo This file is only here so that the containing folder will be included in the NuGet package, it is safe to delete. > .\_BuildOutput\WebApp\Views\MacroPartials\dummy.txt
|
||||
|
||||
ECHO Adding Web.config transform files to the NuGet package
|
||||
ren .\_BuildOutput\WebApp\MacroScripts\Web.config Web.config.transform
|
||||
ren .\_BuildOutput\WebApp\Views\Web.config Web.config.transform
|
||||
|
||||
ECHO Packing the NuGet release files
|
||||
..\src\.nuget\NuGet.exe pack NuSpecs\UmbracoCms.Core.nuspec -Version %version%
|
||||
..\src\.nuget\NuGet.exe pack NuSpecs\UmbracoCms.nuspec -Version %version%
|
||||
|
||||
|
||||
+1
-1
@@ -267,7 +267,7 @@
|
||||
<Message Text="Compiling web project to build\$(BuildFolder)" Importance="high" />
|
||||
<!-- For UseWPP_CopyWebApplication=True see http://stackoverflow.com/questions/1983575/copywebapplication-with-web-config-transformations -->
|
||||
<!-- Build the Umbraco.Web.UI project -->
|
||||
<MSBuild Projects="..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj" Properties="WarningLevel=0;Configuration=$(BuildConfiguration);UseWPP_CopyWebApplication=True;PipelineDependsOnBuild=False;OutDir=$(SolutionBinFolderAbsolutePath);WebProjectOutputDir=$(WebAppFolderAbsolutePath)" Targets="Clean;Build;" BuildInParallel="False" ToolsVersion="4.0" UnloadProjectsOnCompletion="False">
|
||||
<MSBuild Projects="..\src\Umbraco.Web.UI\Umbraco.Web.UI.csproj" Properties="WarningLevel=0;Configuration=$(BuildConfiguration);UseWPP_CopyWebApplication=True;PipelineDependsOnBuild=False;OutDir=$(SolutionBinFolderAbsolutePath);WebProjectOutputDir=$(WebAppFolderAbsolutePath)" Targets="Clean;Rebuild;" BuildInParallel="False" ToolsVersion="4.0" UnloadProjectsOnCompletion="False">
|
||||
</MSBuild>
|
||||
|
||||
<!-- DONE -->
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
@ECHO OFF
|
||||
ECHO Installing Npm NuGet Package
|
||||
|
||||
SET nuGetFolder=%CD%\..\src\packages\
|
||||
ECHO Configured packages folder: %nuGetFolder%
|
||||
ECHO Current folder: %CD%
|
||||
|
||||
%CD%\..\src\.nuget\NuGet.exe install Npm.js -OutputDirectory %nuGetFolder%
|
||||
|
||||
for /f "delims=" %%A in ('dir %nuGetFolder%node.js.* /b') do set "nodePath=%nuGetFolder%%%A\"
|
||||
for /f "delims=" %%A in ('dir %nuGetFolder%npm.js.* /b') do set "npmPath=%nuGetFolder%%%A\tools\"
|
||||
|
||||
ECHO Temporarily adding Npm and Node to path
|
||||
SET oldPath=%PATH%
|
||||
|
||||
path=%npmPath%;%nodePath%;%PATH%
|
||||
|
||||
SET buildFolder=%CD%
|
||||
|
||||
ECHO Change directory to %CD%\..\src\Umbraco.Web.UI.Client\
|
||||
CD %CD%\..\src\Umbraco.Web.UI.Client\
|
||||
|
||||
ECHO Do npm install and the grunt build of Belle
|
||||
call npm install
|
||||
call npm install -g grunt-cli
|
||||
call grunt build
|
||||
|
||||
ECHO Reset path to what it was before
|
||||
path=%oldPath%
|
||||
|
||||
ECHO Move back to the build folder
|
||||
CD %buildFolder%
|
||||
@@ -26,7 +26,7 @@
|
||||
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.6.5]" />
|
||||
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.7.0, 2.0.0)" />
|
||||
<!--<dependency id="ClientDependency" version="[1.7.0, 2.0.0)" />-->
|
||||
<dependency id="ClientDependency-Mvc" version="[1.7.0, 2.0.0)" />
|
||||
<dependency id="AutoMapper" version="[3.0.0, 4.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[4.5.11, 5.0.0)" />
|
||||
@@ -35,6 +35,7 @@
|
||||
<files>
|
||||
<file src="..\_BuildOutput\WebApp\bin\businesslogic.dll" target="lib\businesslogic.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\businesslogic.xml" target="lib\businesslogic.xml" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\ClientDependency.Core.dll" target="lib\ClientDependency.Core.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\cms.dll" target="lib\cms.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\cms.xml" target="lib\cms.xml" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\controls.dll" target="lib\controls.dll" />
|
||||
@@ -45,9 +46,6 @@
|
||||
<file src="..\_BuildOutput\WebApp\bin\log4net.dll" target="lib\log4net.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Microsoft.ApplicationBlocks.Data.dll" target="lib\Microsoft.ApplicationBlocks.Data.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Microsoft.Web.Helpers.dll" target="lib\Microsoft.Web.Helpers.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Our.Umbraco.uGoLive.47x.dll" target="lib\Our.Umbraco.uGoLive.47x.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Our.Umbraco.uGoLive.Checks.dll" target="lib\Our.Umbraco.uGoLive.Checks.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\Our.Umbraco.uGoLive.dll" target="lib\Our.Umbraco.uGoLive.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\SQLCE4Umbraco.dll" target="lib\SQLCE4Umbraco.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\System.Data.SqlServerCe.dll" target="lib\System.Data.SqlServerCe.dll" />
|
||||
<file src="..\_BuildOutput\WebApp\bin\System.Data.SqlServerCe.Entity.dll" target="lib\System.Data.SqlServerCe.Entity.dll" />
|
||||
|
||||
Binary file not shown.
+12
-27
@@ -18,13 +18,13 @@
|
||||
|
||||
<ItemGroup Condition=" '$(PackageSources)' == '' ">
|
||||
<!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
|
||||
<!-- The official NuGet package source (https://nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
|
||||
<!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
|
||||
<!--
|
||||
<PackageSource Include="https://nuget.org/api/v2/" />
|
||||
<PackageSource Include="https://www.nuget.org/api/v2/" />
|
||||
<PackageSource Include="https://my-nuget-source/nuget/" />
|
||||
-->
|
||||
<PackageSource Include="https://nuget.org/api/v2/" />
|
||||
<PackageSource Include="http://www.myget.org/F/umbracocore/" />
|
||||
<PackageSource Include="http://www.myget.org/F/umbracocore/" />
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
|
||||
@@ -41,7 +41,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- NuGet command -->
|
||||
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\nuget.exe</NuGetExePath>
|
||||
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\NuGet.exe</NuGetExePath>
|
||||
<PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
|
||||
|
||||
<NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
|
||||
@@ -50,9 +50,14 @@
|
||||
<PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
|
||||
|
||||
<RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
|
||||
<NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>
|
||||
|
||||
<PaddedSolutionDir Condition=" '$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir>
|
||||
<PaddedSolutionDir Condition=" '$(OS)' != 'Windows_NT' ">"$(SolutionDir)"</PaddedSolutionDir>
|
||||
|
||||
<!-- Commands -->
|
||||
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(RequireConsentSwitch) -solutionDir "$(SolutionDir) "</RestoreCommand>
|
||||
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -p Configuration=$(Configuration) -o "$(PackageOutputDir)" -symbols</BuildCommand>
|
||||
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>
|
||||
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>
|
||||
|
||||
<!-- We need to ensure packages are restored prior to assembly resolve -->
|
||||
<BuildDependsOn Condition="$(RestorePackages) == 'true'">
|
||||
@@ -70,7 +75,6 @@
|
||||
<Target Name="CheckPrerequisites">
|
||||
<!-- Raise an error if we're unable to locate nuget.exe -->
|
||||
<Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
|
||||
<SetEnvironmentVariable EnvKey="VisualStudioVersion" EnvValue="$(VisualStudioVersion)" Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' " />
|
||||
<!--
|
||||
Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
|
||||
This effectively acts as a lock that makes sure that the download operation will only happen once and all
|
||||
@@ -119,7 +123,7 @@
|
||||
|
||||
Log.LogMessage("Downloading latest version of NuGet.exe...");
|
||||
WebClient webClient = new WebClient();
|
||||
webClient.DownloadFile("https://nuget.org/nuget.exe", OutputFilename);
|
||||
webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -131,23 +135,4 @@
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
|
||||
<UsingTask TaskName="SetEnvironmentVariable" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
|
||||
<ParameterGroup>
|
||||
<EnvKey ParameterType="System.String" Required="true" />
|
||||
<EnvValue ParameterType="System.String" Required="true" />
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Using Namespace="System" />
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
try {
|
||||
Environment.SetEnvironmentVariable(EnvKey, EnvValue, System.EnvironmentVariableTarget.Process);
|
||||
}
|
||||
catch {
|
||||
}
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
</Project>
|
||||
+1
-1
@@ -6,7 +6,7 @@ using System.Threading;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
internal abstract class DictionaryCacheProdiverBase : ICacheProvider
|
||||
internal abstract class DictionaryCacheProviderBase : ICacheProvider
|
||||
{
|
||||
protected static readonly ReaderWriterLockSlim Locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
|
||||
protected abstract DictionaryCacheWrapper DictionaryCache { get; }
|
||||
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Cache
|
||||
/// <summary>
|
||||
/// A cache provider that caches items in the HttpContext.Items
|
||||
/// </summary>
|
||||
internal class HttpRequestCacheProvider : DictionaryCacheProdiverBase
|
||||
internal class HttpRequestCacheProvider : DictionaryCacheProviderBase
|
||||
{
|
||||
private readonly Func<HttpContextBase> _context;
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Umbraco.Core.Cache
|
||||
/// <summary>
|
||||
/// A CacheProvider that wraps the logic of the HttpRuntime.Cache
|
||||
/// </summary>
|
||||
internal class HttpRuntimeCacheProvider : DictionaryCacheProdiverBase, IRuntimeCacheProvider
|
||||
internal class HttpRuntimeCacheProvider : DictionaryCacheProviderBase, IRuntimeCacheProvider
|
||||
{
|
||||
private readonly System.Web.Caching.Cache _cache;
|
||||
private readonly DictionaryCacheWrapper _wrapper;
|
||||
|
||||
@@ -268,7 +268,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// <param name="value">Value of the setting to be saved.</param>
|
||||
internal static void SaveSetting(string key, string value)
|
||||
{
|
||||
var fileName = IOHelper.MapPath(string.Format("{0}/appSettings.config", SystemDirectories.Config));
|
||||
var fileName = IOHelper.MapPath(string.Format("{0}/web.config", SystemDirectories.Root));
|
||||
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
|
||||
|
||||
var appSettings = xml.Root.DescendantsAndSelf("appSettings").Single();
|
||||
@@ -290,7 +290,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// <param name="key">Key of the setting to be removed.</param>
|
||||
internal static void RemoveSetting(string key)
|
||||
{
|
||||
var fileName = IOHelper.MapPath(string.Format("{0}/appSettings.config", SystemDirectories.Config));
|
||||
var fileName = IOHelper.MapPath(string.Format("{0}/web.config", SystemDirectories.Root));
|
||||
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
|
||||
|
||||
var appSettings = xml.Root.DescendantsAndSelf("appSettings").Single();
|
||||
@@ -697,8 +697,12 @@ namespace Umbraco.Core.Configuration
|
||||
StartsWithContainer _newReservedList = new StartsWithContainer();
|
||||
foreach (string reservedUrl in _reservedUrlsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(reservedUrl))
|
||||
continue;
|
||||
|
||||
|
||||
//resolves the url to support tilde chars
|
||||
string reservedUrlTrimmed = IOHelper.ResolveUrl(reservedUrl).Trim().ToLower();
|
||||
string reservedUrlTrimmed = IOHelper.ResolveUrl(reservedUrl.Trim()).Trim().ToLower();
|
||||
if (reservedUrlTrimmed.Length > 0)
|
||||
_newReservedList.Add(reservedUrlTrimmed);
|
||||
}
|
||||
@@ -706,8 +710,11 @@ namespace Umbraco.Core.Configuration
|
||||
foreach (string reservedPath in _reservedPathsCache.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries))
|
||||
{
|
||||
bool trimEnd = !reservedPath.EndsWith("/");
|
||||
if (string.IsNullOrWhiteSpace(reservedPath))
|
||||
continue;
|
||||
|
||||
//resolves the url to support tilde chars
|
||||
string reservedPathTrimmed = IOHelper.ResolveUrl(reservedPath).Trim().ToLower();
|
||||
string reservedPathTrimmed = IOHelper.ResolveUrl(reservedPath.Trim()).Trim().ToLower();
|
||||
|
||||
if (reservedPathTrimmed.Length > 0)
|
||||
_newReservedList.Add(reservedPathTrimmed + (reservedPathTrimmed.EndsWith("/") ? "" : "/"));
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
return new OptionalInnerTextConfigurationElement<bool>(
|
||||
(InnerTextConfigurationElement<bool>)this["ResolveUrlsFromTextString"],
|
||||
//set the default
|
||||
true);
|
||||
false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
bool RemoveDoubleDashes { get; }
|
||||
|
||||
bool ConvertUrlsToAscii { get; }
|
||||
|
||||
IEnumerable<IChar> CharCollection { get; }
|
||||
}
|
||||
}
|
||||
@@ -121,6 +121,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return UrlReplacing.RemoveDoubleDashes; }
|
||||
}
|
||||
|
||||
bool IRequestHandlerSection.ConvertUrlsToAscii
|
||||
{
|
||||
get { return UrlReplacing.ConvertUrlsToAscii; }
|
||||
}
|
||||
|
||||
IEnumerable<IChar> IRequestHandlerSection.CharCollection
|
||||
{
|
||||
get { return UrlReplacing.CharCollection; }
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
return new OptionalInnerTextConfigurationElement<string>(
|
||||
(InnerTextConfigurationElement<string>)this["authCookieName"],
|
||||
//set the default
|
||||
"UMB_UCONTEXT");
|
||||
Constants.Web.AuthCookieName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return (bool) base["removeDoubleDashes"]; }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("toAscii", DefaultValue = false)]
|
||||
internal bool ConvertUrlsToAscii
|
||||
{
|
||||
get { return (bool)base["toAscii"]; }
|
||||
}
|
||||
|
||||
[ConfigurationCollection(typeof(CharCollection), AddItemName = "char")]
|
||||
[ConfigurationProperty("", IsDefaultCollection = true)]
|
||||
internal CharCollection CharCollection
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.0.0");
|
||||
private static readonly Version Version = new Version("7.0.2");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
|
||||
@@ -171,131 +171,84 @@ namespace Umbraco.Core
|
||||
|
||||
public const string FailedPasswordAttemptsLabel = "Failed Password Attempts";
|
||||
|
||||
internal static Dictionary<string, PropertyType>
|
||||
StandardPropertyTypeStubs = new Dictionary<string, PropertyType>
|
||||
{
|
||||
{
|
||||
Comments,
|
||||
new PropertyType(
|
||||
PropertyEditors
|
||||
.TextboxMultipleAlias,
|
||||
DataTypeDatabaseType
|
||||
.Ntext)
|
||||
{
|
||||
Alias = Comments,
|
||||
Name =
|
||||
CommentsLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
FailedPasswordAttempts,
|
||||
new PropertyType(
|
||||
PropertyEditors
|
||||
.IntegerAlias,
|
||||
DataTypeDatabaseType
|
||||
.Integer)
|
||||
{
|
||||
Alias =
|
||||
FailedPasswordAttempts,
|
||||
Name =
|
||||
FailedPasswordAttemptsLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
IsApproved,
|
||||
new PropertyType(
|
||||
PropertyEditors
|
||||
.TrueFalseAlias,
|
||||
DataTypeDatabaseType
|
||||
.Integer)
|
||||
{
|
||||
Alias = IsApproved,
|
||||
Name =
|
||||
IsApprovedLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
IsLockedOut,
|
||||
new PropertyType(
|
||||
PropertyEditors
|
||||
.TrueFalseAlias,
|
||||
DataTypeDatabaseType
|
||||
.Integer)
|
||||
{
|
||||
Alias =
|
||||
IsLockedOut,
|
||||
Name =
|
||||
IsLockedOutLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastLockoutDate,
|
||||
new PropertyType(
|
||||
PropertyEditors.DateAlias,
|
||||
DataTypeDatabaseType
|
||||
.Date)
|
||||
{
|
||||
Alias =
|
||||
LastLockoutDate,
|
||||
Name =
|
||||
LastLockoutDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastLoginDate,
|
||||
new PropertyType(
|
||||
PropertyEditors.DateAlias,
|
||||
DataTypeDatabaseType
|
||||
.Date)
|
||||
{
|
||||
Alias =
|
||||
LastLoginDate,
|
||||
Name =
|
||||
LastLoginDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastPasswordChangeDate,
|
||||
new PropertyType(
|
||||
PropertyEditors.DateAlias,
|
||||
DataTypeDatabaseType
|
||||
.Date)
|
||||
{
|
||||
Alias =
|
||||
LastPasswordChangeDate,
|
||||
Name =
|
||||
LastPasswordChangeDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
PasswordAnswer,
|
||||
new PropertyType(
|
||||
PropertyEditors
|
||||
.TextboxAlias,
|
||||
DataTypeDatabaseType
|
||||
.Nvarchar)
|
||||
{
|
||||
Alias =
|
||||
PasswordAnswer,
|
||||
Name =
|
||||
PasswordAnswerLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
PasswordQuestion,
|
||||
new PropertyType(
|
||||
PropertyEditors
|
||||
.TextboxAlias,
|
||||
DataTypeDatabaseType
|
||||
.Nvarchar)
|
||||
{
|
||||
Alias =
|
||||
PasswordQuestion,
|
||||
Name =
|
||||
PasswordQuestionLabel
|
||||
}
|
||||
}
|
||||
};
|
||||
internal static Dictionary<string, PropertyType> GetStandardPropertyTypeStubs()
|
||||
{
|
||||
return new Dictionary<string, PropertyType>
|
||||
{
|
||||
{
|
||||
Comments,
|
||||
new PropertyType(PropertyEditors.TextboxMultipleAlias, DataTypeDatabaseType.Ntext)
|
||||
{
|
||||
Alias = Comments,
|
||||
Name = CommentsLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
FailedPasswordAttempts,
|
||||
new PropertyType(PropertyEditors.IntegerAlias, DataTypeDatabaseType.Integer)
|
||||
{
|
||||
Alias = FailedPasswordAttempts,
|
||||
Name = FailedPasswordAttemptsLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
IsApproved,
|
||||
new PropertyType(PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer)
|
||||
{
|
||||
Alias = IsApproved,
|
||||
Name = IsApprovedLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
IsLockedOut,
|
||||
new PropertyType(PropertyEditors.TrueFalseAlias, DataTypeDatabaseType.Integer)
|
||||
{
|
||||
Alias = IsLockedOut,
|
||||
Name = IsLockedOutLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastLockoutDate,
|
||||
new PropertyType(PropertyEditors.DateAlias, DataTypeDatabaseType.Date)
|
||||
{
|
||||
Alias = LastLockoutDate,
|
||||
Name = LastLockoutDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastLoginDate,
|
||||
new PropertyType(PropertyEditors.DateAlias, DataTypeDatabaseType.Date)
|
||||
{
|
||||
Alias = LastLoginDate,
|
||||
Name = LastLoginDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
LastPasswordChangeDate,
|
||||
new PropertyType(PropertyEditors.DateAlias, DataTypeDatabaseType.Date)
|
||||
{
|
||||
Alias = LastPasswordChangeDate,
|
||||
Name = LastPasswordChangeDateLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
PasswordAnswer,
|
||||
new PropertyType(PropertyEditors.TextboxAlias, DataTypeDatabaseType.Nvarchar)
|
||||
{
|
||||
Alias = PasswordAnswer,
|
||||
Name = PasswordAnswerLabel
|
||||
}
|
||||
},
|
||||
{
|
||||
PasswordQuestion,
|
||||
new PropertyType(PropertyEditors.TextboxAlias, DataTypeDatabaseType.Nvarchar)
|
||||
{
|
||||
Alias = PasswordQuestion,
|
||||
Name = PasswordQuestionLabel
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -307,6 +260,8 @@ namespace Umbraco.Core
|
||||
/// MemberType alias for default member type.
|
||||
/// </summary>
|
||||
public const string Member = "Member";
|
||||
|
||||
public const string SystemDefaultProtectType = "_umbracoSystemDefaultProtectType";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public static partial class Constants
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the identifiers for Umbraco system nodes.
|
||||
/// </summary>
|
||||
public static class Web
|
||||
{
|
||||
/// <summary>
|
||||
/// The preview cookie name
|
||||
/// </summary>
|
||||
public const string PreviewCookieName = "UMB_PREVIEW";
|
||||
|
||||
/// <summary>
|
||||
/// The auth cookie name
|
||||
/// </summary>
|
||||
public const string AuthCookieName = "UMB_UCONTEXT";
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,7 +64,7 @@ namespace Umbraco.Core
|
||||
InitializeProfilerResolver();
|
||||
|
||||
_timer = DisposableTimer.DebugDuration<CoreBootManager>("Umbraco application starting", "Umbraco application startup complete");
|
||||
|
||||
|
||||
CreateApplicationCache();
|
||||
|
||||
//Create the legacy prop-eds mapping
|
||||
@@ -223,10 +223,7 @@ namespace Umbraco.Core
|
||||
throw new InvalidOperationException("The boot manager has already been completed");
|
||||
|
||||
FreezeResolution();
|
||||
|
||||
//stop the timer and log the output
|
||||
_timer.Dispose();
|
||||
|
||||
|
||||
//call OnApplicationStarting of each application events handler
|
||||
ApplicationEventsResolver.Current.ApplicationEventHandlers
|
||||
.ForEach(x => x.OnApplicationStarted(UmbracoApplication, ApplicationContext));
|
||||
@@ -244,6 +241,9 @@ namespace Umbraco.Core
|
||||
// we're ready to serve content!
|
||||
ApplicationContext.IsReady = true;
|
||||
|
||||
//stop the timer and log the output
|
||||
_timer.Dispose();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -268,7 +268,9 @@ namespace Umbraco.Core
|
||||
{
|
||||
new Lazy<Type>(() => typeof (RequiredManifestValueValidator)),
|
||||
new Lazy<Type>(() => typeof (RegexValidator)),
|
||||
new Lazy<Type>(() => typeof (DelimitedManifestValueValidator))
|
||||
new Lazy<Type>(() => typeof (DelimitedManifestValueValidator)),
|
||||
new Lazy<Type>(() => typeof (EmailValidator)),
|
||||
new Lazy<Type>(() => typeof (IntegerValidator)),
|
||||
});
|
||||
|
||||
//by default we'll use the standard configuration based sync
|
||||
@@ -322,17 +324,10 @@ namespace Umbraco.Core
|
||||
// fixme - why not use the following syntax?
|
||||
//PluginManager.Current.ResolveTypes<IPropertyValueConverter>());
|
||||
|
||||
// use the new DefaultShortStringHelper but sort-of remain compatible
|
||||
// - use UmbracoSettings UrlReplaceCharacters
|
||||
// - allow underscores in terms, allow leading digits
|
||||
// use the new DefaultShortStringHelper
|
||||
ShortStringHelperResolver.Current = new ShortStringHelperResolver(
|
||||
new DefaultShortStringHelper()
|
||||
.WithConfig(CleanStringType.Url, DefaultShortStringHelper.ApplyUrlReplaceCharacters,
|
||||
allowUnderscoreInTerm: true, allowLeadingDigits: true));
|
||||
|
||||
// that was the old one
|
||||
//ShortStringHelperResolver.Current = new ShortStringHelperResolver(
|
||||
// new LegacyShortStringHelper());
|
||||
//new LegacyShortStringHelper());
|
||||
new DefaultShortStringHelper().WithDefaultConfig());
|
||||
|
||||
UrlSegmentProviderResolver.Current = new UrlSegmentProviderResolver(
|
||||
typeof (DefaultUrlSegmentProvider));
|
||||
|
||||
@@ -250,7 +250,7 @@ namespace Umbraco.Core
|
||||
_connectionString = connectionString;
|
||||
_providerName = providerName;
|
||||
|
||||
var fileName = IOHelper.MapPath(string.Format("{0}/connectionStrings.config", SystemDirectories.Config));
|
||||
var fileName = IOHelper.MapPath(string.Format("{0}/web.config", SystemDirectories.Root));
|
||||
var xml = XDocument.Load(fileName, LoadOptions.PreserveWhitespace);
|
||||
var connectionstrings = xml.Root.DescendantsAndSelf("connectionStrings").Single();
|
||||
|
||||
@@ -424,24 +424,19 @@ namespace Umbraco.Core
|
||||
return _result;
|
||||
}
|
||||
|
||||
internal Result CreateDatabaseSchemaAndDataOrUpgrade()
|
||||
internal Result CreateDatabaseSchemaAndData()
|
||||
{
|
||||
if (_configured == false || (string.IsNullOrEmpty(_connectionString) || string.IsNullOrEmpty(ProviderName)))
|
||||
var readyForInstall = CheckReadyForInstall();
|
||||
if (readyForInstall.Success == false)
|
||||
{
|
||||
return new Result
|
||||
{
|
||||
Message =
|
||||
"Database configuration is invalid. Please check that the entered database exists and that the provided username and password has write access to the database.",
|
||||
Success = false,
|
||||
Percentage = "10"
|
||||
};
|
||||
return readyForInstall.Result;
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
LogHelper.Info<DatabaseContext>("Database configuration status: Started");
|
||||
|
||||
var message = string.Empty;
|
||||
string message;
|
||||
|
||||
var database = new UmbracoDatabase(_connectionString, ProviderName);
|
||||
var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database);
|
||||
@@ -456,50 +451,73 @@ namespace Umbraco.Core
|
||||
|
||||
return new Result { Message = message, Success = false, Percentage = "15" };
|
||||
}
|
||||
else if (supportsCaseInsensitiveQueries == null)
|
||||
{
|
||||
message = "<p> </p><p>Warning! Could not check if your database type supports case insensitive queries. <br />We currently do not support these databases that do not support case insensitive queries.</p>" +
|
||||
"<p>You can check this by looking for the following setting in your my.ini file in your MySQL installation directory:</p>" +
|
||||
"<pre>lower_case_table_names=1</pre><br />" +
|
||||
"<p>Note: Make sure to check with your hosting provider if they support case insensitive queries as well.</p>" +
|
||||
"<p>For more technical information on case sensitivity in MySQL, have a look at " +
|
||||
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
|
||||
}
|
||||
else
|
||||
{
|
||||
if (SqlSyntaxContext.SqlSyntaxProvider.GetType() == typeof(MySqlSyntaxProvider))
|
||||
{
|
||||
message = "<p> </p><p>Congratulations, the database step ran successfully!</p>" +
|
||||
"<p>Note: You're using MySQL and the database instance you're connecting to seems to support case insensitive queries.</p>" +
|
||||
"<p>However, your hosting provider may not support this option. Umbraco does not currently support MySQL installs that do not support case insensitive queries</p>" +
|
||||
"<p>Make sure to check with your hosting provider if they support case insensitive queries as well.</p>" +
|
||||
"<p>They can check this by looking for the following setting in the my.ini file in their MySQL installation directory:</p>" +
|
||||
"<pre>lower_case_table_names=1</pre><br />" +
|
||||
"<p>For more technical information on case sensitivity in MySQL, have a look at " +
|
||||
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
|
||||
}
|
||||
}
|
||||
|
||||
message = GetResultMessageForMySql(supportsCaseInsensitiveQueries);
|
||||
|
||||
var schemaResult = ValidateDatabaseSchema();
|
||||
var installedVersion = schemaResult.DetermineInstalledVersion();
|
||||
|
||||
|
||||
//If Configuration Status is empty and the determined version is "empty" its a new install - otherwise upgrade the existing
|
||||
if (string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus) && installedVersion.Equals(new Version(0, 0, 0)))
|
||||
{
|
||||
database.CreateDatabaseSchema();
|
||||
message = message + "<p>Installation completed!</p>";
|
||||
|
||||
//now that everything is done, we need to determine the version of SQL server that is executing
|
||||
LogHelper.Info<DatabaseContext>("Database configuration status: " + message);
|
||||
return new Result { Message = message, Success = true, Percentage = "100" };
|
||||
}
|
||||
else
|
||||
{
|
||||
var configuredVersion = string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus)
|
||||
|
||||
//we need to do an upgrade so return a new status message and it will need to be done during the next step
|
||||
LogHelper.Info<DatabaseContext>("Database requires upgrade");
|
||||
message = "<p>Upgrading database, this may take some time...</p>";
|
||||
return new Result
|
||||
{
|
||||
RequiresUpgrade = true,
|
||||
Message = message,
|
||||
Success = true,
|
||||
Percentage = "30"
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return HandleInstallException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This assumes all of the previous checks are done!
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal Result UpgradeSchemaAndData()
|
||||
{
|
||||
var readyForInstall = CheckReadyForInstall();
|
||||
if (readyForInstall.Success == false)
|
||||
{
|
||||
return readyForInstall.Result;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
LogHelper.Info<DatabaseContext>("Database upgrade started");
|
||||
|
||||
var database = new UmbracoDatabase(_connectionString, ProviderName);
|
||||
var supportsCaseInsensitiveQueries = SqlSyntaxContext.SqlSyntaxProvider.SupportsCaseInsensitiveQueries(database);
|
||||
|
||||
var message = GetResultMessageForMySql(supportsCaseInsensitiveQueries);
|
||||
|
||||
var schemaResult = ValidateDatabaseSchema();
|
||||
var installedVersion = schemaResult.DetermineInstalledVersion();
|
||||
|
||||
//DO the upgrade!
|
||||
|
||||
var configuredVersion = string.IsNullOrEmpty(GlobalSettings.ConfigurationStatus)
|
||||
? installedVersion
|
||||
: new Version(GlobalSettings.ConfigurationStatus);
|
||||
var targetVersion = UmbracoVersion.Current;
|
||||
var runner = new MigrationRunner(configuredVersion, targetVersion, GlobalSettings.UmbracoMigrationName);
|
||||
var upgraded = runner.Execute(database, true);
|
||||
message = message + "<p>Upgrade completed!</p>";
|
||||
}
|
||||
var targetVersion = UmbracoVersion.Current;
|
||||
var runner = new MigrationRunner(configuredVersion, targetVersion, GlobalSettings.UmbracoMigrationName);
|
||||
var upgraded = runner.Execute(database, true);
|
||||
message = message + "<p>Upgrade completed!</p>";
|
||||
|
||||
//now that everything is done, we need to determine the version of SQL server that is executing
|
||||
|
||||
@@ -509,26 +527,72 @@ namespace Umbraco.Core
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogHelper.Info<DatabaseContext>("Database configuration failed with the following error and stack trace: " + ex.Message + "\n" + ex.StackTrace);
|
||||
|
||||
if (_result != null)
|
||||
{
|
||||
LogHelper.Info<DatabaseContext>("The database schema validation produced the following summary: \n" + _result.GetSummary());
|
||||
}
|
||||
|
||||
return new Result
|
||||
{
|
||||
Message =
|
||||
"The database configuration failed with the following message: " + ex.Message +
|
||||
"\n Please check log file for additional information (can be found in '/App_Data/Logs/UmbracoTraceLog.txt')",
|
||||
Success = false,
|
||||
Percentage = "90"
|
||||
};
|
||||
return HandleInstallException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private string GetResultMessageForMySql(bool? supportsCaseInsensitiveQueries)
|
||||
{
|
||||
if (supportsCaseInsensitiveQueries == null)
|
||||
{
|
||||
return "<p> </p><p>Warning! Could not check if your database type supports case insensitive queries. <br />We currently do not support these databases that do not support case insensitive queries.</p>" +
|
||||
"<p>You can check this by looking for the following setting in your my.ini file in your MySQL installation directory:</p>" +
|
||||
"<pre>lower_case_table_names=1</pre><br />" +
|
||||
"<p>Note: Make sure to check with your hosting provider if they support case insensitive queries as well.</p>" +
|
||||
"<p>For more technical information on case sensitivity in MySQL, have a look at " +
|
||||
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
|
||||
}
|
||||
if (SqlSyntaxContext.SqlSyntaxProvider.GetType() == typeof(MySqlSyntaxProvider))
|
||||
{
|
||||
return "<p> </p><p>Congratulations, the database step ran successfully!</p>" +
|
||||
"<p>Note: You're using MySQL and the database instance you're connecting to seems to support case insensitive queries.</p>" +
|
||||
"<p>However, your hosting provider may not support this option. Umbraco does not currently support MySQL installs that do not support case insensitive queries</p>" +
|
||||
"<p>Make sure to check with your hosting provider if they support case insensitive queries as well.</p>" +
|
||||
"<p>They can check this by looking for the following setting in the my.ini file in their MySQL installation directory:</p>" +
|
||||
"<pre>lower_case_table_names=1</pre><br />" +
|
||||
"<p>For more technical information on case sensitivity in MySQL, have a look at " +
|
||||
"<a href='http://dev.mysql.com/doc/refman/5.0/en/identifier-case-sensitivity.html'>the documentation on the subject</a></p>";
|
||||
}
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private Attempt<Result> CheckReadyForInstall()
|
||||
{
|
||||
if (_configured == false || (string.IsNullOrEmpty(_connectionString) || string.IsNullOrEmpty(ProviderName)))
|
||||
{
|
||||
return Attempt.Fail(new Result
|
||||
{
|
||||
Message =
|
||||
"Database configuration is invalid. Please check that the entered database exists and that the provided username and password has write access to the database.",
|
||||
Success = false,
|
||||
Percentage = "10"
|
||||
});
|
||||
}
|
||||
return Attempt<Result>.Succeed();
|
||||
}
|
||||
|
||||
private Result HandleInstallException(Exception ex)
|
||||
{
|
||||
LogHelper.Info<DatabaseContext>("Database configuration failed with the following error and stack trace: " + ex.Message + "\n" + ex.StackTrace);
|
||||
|
||||
if (_result != null)
|
||||
{
|
||||
LogHelper.Info<DatabaseContext>("The database schema validation produced the following summary: \n" + _result.GetSummary());
|
||||
}
|
||||
|
||||
return new Result
|
||||
{
|
||||
Message =
|
||||
"The database configuration failed with the following message: " + ex.Message +
|
||||
"\n Please check log file for additional information (can be found in '/App_Data/Logs/UmbracoTraceLog.txt')",
|
||||
Success = false,
|
||||
Percentage = "90"
|
||||
};
|
||||
}
|
||||
|
||||
internal class Result
|
||||
{
|
||||
public bool RequiresUpgrade { get; set; }
|
||||
public string Message { get; set; }
|
||||
public bool Success { get; set; }
|
||||
public string Percentage { get; set; }
|
||||
|
||||
@@ -231,7 +231,7 @@ namespace Umbraco.Core
|
||||
/// <returns>The contains key ignore case.</returns>
|
||||
public static bool ContainsKeyIgnoreCase<TValue>(this IDictionary<string, TValue> dictionary, string key)
|
||||
{
|
||||
return dictionary.Keys.Any(i => i.Equals(key, StringComparison.CurrentCultureIgnoreCase));
|
||||
return dictionary.Keys.InvariantContains(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -257,9 +257,9 @@ namespace Umbraco.Core
|
||||
/// <param name="key">The key.</param>
|
||||
/// <typeparam name="TValue">The type</typeparam>
|
||||
/// <returns>The entry</returns>
|
||||
public static TValue GetEntryIgnoreCase<TValue>(this IDictionary<string, TValue> dictionary, string key)
|
||||
public static TValue GetValueIgnoreCase<TValue>(this IDictionary<string, TValue> dictionary, string key)
|
||||
{
|
||||
return dictionary.GetEntryIgnoreCase(key, default(TValue));
|
||||
return dictionary.GetValueIgnoreCase(key, default(TValue));
|
||||
}
|
||||
|
||||
/// <summary>The get entry ignore case.</summary>
|
||||
@@ -268,11 +268,11 @@ namespace Umbraco.Core
|
||||
/// <param name="defaultValue">The default value.</param>
|
||||
/// <typeparam name="TValue">The type</typeparam>
|
||||
/// <returns>The entry</returns>
|
||||
public static TValue GetEntryIgnoreCase<TValue>(this IDictionary<string, TValue> dictionary, string key, TValue defaultValue)
|
||||
public static TValue GetValueIgnoreCase<TValue>(this IDictionary<string, TValue> dictionary, string key, TValue defaultValue)
|
||||
{
|
||||
key = dictionary.Keys.Where(i => i.Equals(key, StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
|
||||
key = dictionary.Keys.FirstOrDefault(i => i.InvariantEquals(key));
|
||||
|
||||
return !key.IsNullOrWhiteSpace()
|
||||
return key.IsNullOrWhiteSpace() == false
|
||||
? dictionary[key]
|
||||
: defaultValue;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class ExportEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting a single entity instance
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="xml"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
public ExportEventArgs(TEntity eventObject, XElement xml, bool canCancel)
|
||||
: base(new List<TEntity> { eventObject }, canCancel)
|
||||
{
|
||||
Xml = xml;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a single entity instance
|
||||
/// and cancellable by default
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="elementName"></param>
|
||||
public ExportEventArgs(TEntity eventObject, string elementName) : base(new List<TEntity> {eventObject}, true)
|
||||
{
|
||||
Xml = new XElement(elementName);
|
||||
}
|
||||
|
||||
protected ExportEventArgs(IEnumerable<TEntity> eventObject, bool canCancel) : base(eventObject, canCancel)
|
||||
{
|
||||
}
|
||||
|
||||
protected ExportEventArgs(IEnumerable<TEntity> eventObject) : base(eventObject)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all entities that were exported during the operation
|
||||
/// </summary>
|
||||
public IEnumerable<TEntity> ExportedEntities
|
||||
{
|
||||
get { return EventObject; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the xml relating to the export event
|
||||
/// </summary>
|
||||
public XElement Xml { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class ImportEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting an XElement with the xml being imported
|
||||
/// </summary>
|
||||
/// <param name="xml"></param>
|
||||
public ImportEventArgs(XElement xml) : base(new List<TEntity>(), true)
|
||||
{
|
||||
Xml = xml;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor accepting a list of entities and an XElement with the imported xml
|
||||
/// </summary>
|
||||
/// <param name="eventObject"></param>
|
||||
/// <param name="xml"></param>
|
||||
/// <param name="canCancel"></param>
|
||||
public ImportEventArgs(IEnumerable<TEntity> eventObject, XElement xml, bool canCancel)
|
||||
: base(eventObject, canCancel)
|
||||
{
|
||||
Xml = xml;
|
||||
}
|
||||
|
||||
protected ImportEventArgs(IEnumerable<TEntity> eventObject, bool canCancel) : base(eventObject, canCancel)
|
||||
{
|
||||
}
|
||||
|
||||
protected ImportEventArgs(IEnumerable<TEntity> eventObject) : base(eventObject)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all entities that were imported during the operation
|
||||
/// </summary>
|
||||
public IEnumerable<TEntity> ImportedEntities
|
||||
{
|
||||
get { return EventObject; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the xml relating to the import event
|
||||
/// </summary>
|
||||
public XElement Xml { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -49,8 +49,5 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
get { return EventObject; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.IO;
|
||||
using System;
|
||||
using System.IO;
|
||||
using Umbraco.Core.CodeAnnotations;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
@@ -30,5 +31,17 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
return Path.GetFileName(fs.GetFullPath(path));
|
||||
}
|
||||
|
||||
//TODO: Currently this is the only way to do this
|
||||
internal static void CreateFolder(this IFileSystem fs, string folderPath)
|
||||
{
|
||||
var path = fs.GetRelativePath(folderPath);
|
||||
var tempFile = Path.Combine(path, Guid.NewGuid().ToString("N") + ".tmp");
|
||||
using (var s = new MemoryStream())
|
||||
{
|
||||
fs.AddFile(tempFile, s);
|
||||
}
|
||||
fs.DeleteFile(tempFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ using Umbraco.Core.CodeAnnotations;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
//TODO: There is no way to create a directory here without creating a file in a directory and then deleting it
|
||||
|
||||
public interface IFileSystem
|
||||
{
|
||||
IEnumerable<string> GetDirectories(string path);
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Umbraco.Core.IO
|
||||
//Replaces tildes with the root dir
|
||||
public static string ResolveUrl(string virtualPath)
|
||||
{
|
||||
if (virtualPath.StartsWith("~"))
|
||||
if (virtualPath.StartsWith("~"))
|
||||
return virtualPath.Replace("~", SystemDirectories.Root).Replace("//", "/");
|
||||
else if (Uri.IsWellFormedUriString(virtualPath, UriKind.Absolute))
|
||||
return virtualPath;
|
||||
|
||||
@@ -2,6 +2,7 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using HtmlAgilityPack;
|
||||
|
||||
namespace Umbraco.Core.Macros
|
||||
{
|
||||
@@ -10,8 +11,8 @@ namespace Umbraco.Core.Macros
|
||||
/// </summary>
|
||||
internal class MacroTagParser
|
||||
{
|
||||
private static readonly Regex MacroRteContent = new Regex(@"(<div.*?>.*?<!--\s*?)(<\?UMBRACO_MACRO.*?/>)(.*?</div>)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
|
||||
private static readonly Regex MacroPersistedFormat = new Regex(@"(<\?UMBRACO_MACRO macroAlias=[""'](\w+?)[""'].+?)(?:/>|>.*?</\?UMBRACO_MACRO>)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
|
||||
private static readonly Regex MacroRteContent = new Regex(@"(<!--\s*?)(<\?UMBRACO_MACRO.*?/>)(\s*?-->)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
|
||||
private static readonly Regex MacroPersistedFormat = new Regex(@"(<\?UMBRACO_MACRO macroAlias=[""']([\w\.]+?)[""'].+?)(?:/>|>.*?</\?UMBRACO_MACRO>)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline);
|
||||
|
||||
/// <summary>
|
||||
/// This formats the persisted string to something useful for the rte so that the macro renders properly since we
|
||||
@@ -38,8 +39,8 @@ namespace Umbraco.Core.Macros
|
||||
//<div class="umb-macro-holder myMacro mceNonEditable">
|
||||
var alias = match.Groups[2].Value;
|
||||
var sb = new StringBuilder("<div class=\"umb-macro-holder ");
|
||||
sb.Append(alias);
|
||||
sb.Append(" mceNonEditable\"");
|
||||
//sb.Append(alias.ToSafeAlias());
|
||||
sb.Append("mceNonEditable\"");
|
||||
foreach (var htmlAttribute in htmlAttributes)
|
||||
{
|
||||
sb.Append(" ");
|
||||
@@ -88,7 +89,34 @@ namespace Umbraco.Core.Macros
|
||||
/// </remarks>
|
||||
internal static string FormatRichTextContentForPersistence(string rteContent)
|
||||
{
|
||||
return MacroRteContent.Replace(rteContent, match =>
|
||||
if (string.IsNullOrEmpty(rteContent))
|
||||
{
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var html = new HtmlDocument();
|
||||
html.LoadHtml(rteContent);
|
||||
|
||||
//get all the comment nodes we want
|
||||
var commentNodes = html.DocumentNode.SelectNodes("//comment()[contains(., '<?UMBRACO_MACRO')]");
|
||||
if (commentNodes == null)
|
||||
{
|
||||
//There are no macros found, just return the normal content
|
||||
return rteContent;
|
||||
}
|
||||
|
||||
//replace each containing parent <div> with the comment node itself.
|
||||
foreach (var c in commentNodes)
|
||||
{
|
||||
var div = c.ParentNode;
|
||||
var divContainer = div.ParentNode;
|
||||
divContainer.ReplaceChild(c, div);
|
||||
}
|
||||
|
||||
var parsed = html.DocumentNode.OuterHtml;
|
||||
|
||||
//now replace all the <!-- and --> with nothing
|
||||
return MacroRteContent.Replace(parsed, match =>
|
||||
{
|
||||
if (match.Groups.Count >= 3)
|
||||
{
|
||||
@@ -96,7 +124,7 @@ namespace Umbraco.Core.Macros
|
||||
return match.Groups[2].Value;
|
||||
}
|
||||
//replace with nothing if we couldn't find the syntax for whatever reason
|
||||
return "";
|
||||
return string.Empty;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,15 @@ namespace Umbraco.Core.Media
|
||||
return codec.MimeType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the thumbnails if the image is larger than all of the specified ones.
|
||||
/// </summary>
|
||||
/// <param name="fs"></param>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="extension"></param>
|
||||
/// <param name="originalImage"></param>
|
||||
/// <param name="additionalThumbSizes"></param>
|
||||
/// <returns></returns>
|
||||
internal static IEnumerable<ResizedImage> GenerateMediaThumbnails(
|
||||
IFileSystem fs,
|
||||
string fileName,
|
||||
@@ -32,22 +41,33 @@ namespace Umbraco.Core.Media
|
||||
Image originalImage,
|
||||
IEnumerable<int> additionalThumbSizes)
|
||||
{
|
||||
// Make default thumbnails
|
||||
var thumbs = new List<ResizedImage>
|
||||
{
|
||||
Resize(fs, fileName, extension, 100, "thumb", originalImage),
|
||||
Resize(fs, fileName, extension, 500, "big-thumb", originalImage)
|
||||
};
|
||||
|
||||
//make custom ones
|
||||
foreach (var thumb in additionalThumbSizes.Where(x => x > 0).Distinct())
|
||||
var result = new List<ResizedImage>();
|
||||
|
||||
var allSizes = new List<int> {100, 500};
|
||||
allSizes.AddRange(additionalThumbSizes.Where(x => x > 0).Distinct());
|
||||
|
||||
foreach (var s in allSizes)
|
||||
{
|
||||
thumbs.Add(Resize(fs, fileName, extension, thumb, string.Format("thumb_{0}", thumb), originalImage));
|
||||
if (originalImage.Width >= s && originalImage.Height >= s)
|
||||
{
|
||||
result.Add(Resize(fs, fileName, extension, s, "thumb", originalImage));
|
||||
}
|
||||
}
|
||||
|
||||
return thumbs;
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs an image resize
|
||||
/// </summary>
|
||||
/// <param name="fileSystem"></param>
|
||||
/// <param name="path"></param>
|
||||
/// <param name="extension"></param>
|
||||
/// <param name="maxWidthHeight"></param>
|
||||
/// <param name="fileNameAddition"></param>
|
||||
/// <param name="originalImage"></param>
|
||||
/// <returns></returns>
|
||||
private static ResizedImage Resize(IFileSystem fileSystem, string path, string extension, int maxWidthHeight, string fileNameAddition, Image originalImage)
|
||||
{
|
||||
var fileNameThumb = String.IsNullOrEmpty(fileNameAddition)
|
||||
@@ -105,8 +125,23 @@ namespace Umbraco.Core.Media
|
||||
{
|
||||
using (var g = Graphics.FromImage(bp))
|
||||
{
|
||||
g.SmoothingMode = SmoothingMode.HighQuality;
|
||||
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
//if the image size is rather large we cannot use the best quality interpolation mode
|
||||
// because we'll get out of mem exceptions. So we'll detect how big the image is and use
|
||||
// the mid quality interpolation mode when the image size exceeds our max limit.
|
||||
|
||||
if (image.Width > 5000 || image.Height > 5000)
|
||||
{
|
||||
//use mid quality
|
||||
g.InterpolationMode = InterpolationMode.Bilinear;
|
||||
}
|
||||
else
|
||||
{
|
||||
//use best quality
|
||||
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
|
||||
}
|
||||
|
||||
|
||||
g.SmoothingMode = SmoothingMode.HighQuality;
|
||||
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
|
||||
g.CompositingQuality = CompositingQuality.HighQuality;
|
||||
|
||||
|
||||
@@ -618,7 +618,7 @@ namespace Umbraco.Core.Models
|
||||
/// <returns>Xml representation of the passed in <see cref="IContent"/></returns>
|
||||
internal static XElement ToDeepXml(this IContent content)
|
||||
{
|
||||
return ApplicationContext.Current.Services.PackagingService.Export(content, true);
|
||||
return ApplicationContext.Current.Services.PackagingService.Export(content, true, raiseEvents: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -628,7 +628,7 @@ namespace Umbraco.Core.Models
|
||||
/// <returns>Xml representation of the passed in <see cref="IContent"/></returns>
|
||||
public static XElement ToXml(this IContent content)
|
||||
{
|
||||
return ApplicationContext.Current.Services.PackagingService.Export(content);
|
||||
return ApplicationContext.Current.Services.PackagingService.Export(content, raiseEvents: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -638,24 +638,19 @@ namespace Umbraco.Core.Models
|
||||
/// <returns>Xml representation of the passed in <see cref="IContent"/></returns>
|
||||
public static XElement ToXml(this IMedia media)
|
||||
{
|
||||
return ApplicationContext.Current.Services.PackagingService.Export(media);
|
||||
}
|
||||
|
||||
internal static XElement ToDeepXml(this IMedia media)
|
||||
{
|
||||
return ApplicationContext.Current.Services.PackagingService.Export(media, true);
|
||||
return ApplicationContext.Current.Services.PackagingService.Export(media, raiseEvents: false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the xml representation for the <see cref="IMedia"/> object
|
||||
/// Creates the full xml representation for the <see cref="IMedia"/> object and all of it's descendants
|
||||
/// </summary>
|
||||
/// <param name="member"><see cref="IContent"/> to generate xml for</param>
|
||||
/// <returns>Xml representation of the passed in <see cref="IContent"/></returns>
|
||||
public static XElement ToXml(this IMember member)
|
||||
/// <param name="media"><see cref="IMedia"/> to generate xml for</param>
|
||||
/// <returns>Xml representation of the passed in <see cref="IMedia"/></returns>
|
||||
internal static XElement ToDeepXml(this IMedia media)
|
||||
{
|
||||
return ApplicationContext.Current.Services.PackagingService.Export(member);
|
||||
return ApplicationContext.Current.Services.PackagingService.Export(media, true, raiseEvents: false);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates the xml representation for the <see cref="IContent"/> object
|
||||
/// </summary>
|
||||
@@ -668,6 +663,16 @@ namespace Umbraco.Core.Models
|
||||
//If current IContent is published we should get latest unpublished version
|
||||
return content.ToXml();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the xml representation for the <see cref="IMember"/> object
|
||||
/// </summary>
|
||||
/// <param name="member"><see cref="IMember"/> to generate xml for</param>
|
||||
/// <returns>Xml representation of the passed in <see cref="IContent"/></returns>
|
||||
public static XElement ToXml(this IMember member)
|
||||
{
|
||||
return ((PackagingService)(ApplicationContext.Current.Services.PackagingService)).Export(member);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ namespace Umbraco.Core.Models
|
||||
_allowedContentTypes = new List<ContentTypeSort>();
|
||||
_propertyGroups = new PropertyGroupCollection();
|
||||
_propertyTypes = new PropertyTypeCollection();
|
||||
_propertyTypes.CollectionChanged += PropertyTypesChanged;
|
||||
_additionalData = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
@@ -54,6 +55,7 @@ namespace Umbraco.Core.Models
|
||||
_allowedContentTypes = new List<ContentTypeSort>();
|
||||
_propertyGroups = new PropertyGroupCollection();
|
||||
_propertyTypes = new PropertyTypeCollection();
|
||||
_propertyTypes.CollectionChanged += PropertyTypesChanged;
|
||||
_additionalData = new Dictionary<string, object>();
|
||||
}
|
||||
|
||||
@@ -433,8 +435,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
if (PropertyTypeExists(propertyType.Alias) == false)
|
||||
{
|
||||
_propertyTypes.Add(propertyType);
|
||||
_propertyTypes.CollectionChanged += PropertyTypesChanged;
|
||||
_propertyTypes.Add(propertyType);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
|
||||
@@ -6,6 +6,16 @@ using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
internal sealed class Folder : Entity
|
||||
{
|
||||
public Folder(string folderPath)
|
||||
{
|
||||
Path = folderPath;
|
||||
}
|
||||
|
||||
public string Path { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Represents an abstract file which provides basic functionality for a File with an Alias and Name
|
||||
/// </summary>
|
||||
@@ -23,6 +33,8 @@ namespace Umbraco.Core.Models
|
||||
|
||||
private static readonly PropertyInfo ContentSelector = ExpressionHelper.GetPropertyInfo<File, string>(x => x.Content);
|
||||
private static readonly PropertyInfo PathSelector = ExpressionHelper.GetPropertyInfo<File, string>(x => x.Path);
|
||||
private string _alias;
|
||||
private string _name;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Name of the File including extension
|
||||
@@ -32,7 +44,11 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
get
|
||||
{
|
||||
return new FileInfo(Path).Name;
|
||||
if (_name == null)
|
||||
{
|
||||
_name = System.IO.Path.GetFileName(Path);
|
||||
}
|
||||
return _name;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,10 +60,14 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
get
|
||||
{
|
||||
var fileInfo = new FileInfo(Path);
|
||||
var name = fileInfo.Name;
|
||||
int lastIndexOf = name.LastIndexOf(".", StringComparison.InvariantCultureIgnoreCase);
|
||||
return name.Substring(0, lastIndexOf);
|
||||
if (_alias == null)
|
||||
{
|
||||
var name = System.IO.Path.GetFileName(Path);
|
||||
if (name == null) return string.Empty;
|
||||
var lastIndexOf = name.LastIndexOf(".", StringComparison.InvariantCultureIgnoreCase);
|
||||
_alias = name.Substring(0, lastIndexOf);
|
||||
}
|
||||
return _alias;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,6 +80,10 @@ namespace Umbraco.Core.Models
|
||||
get { return _path; }
|
||||
set
|
||||
{
|
||||
//reset
|
||||
_alias = null;
|
||||
_name = null;
|
||||
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_path = value;
|
||||
|
||||
@@ -1,106 +1,10 @@
|
||||
using System;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
public interface IMember : IContentBase
|
||||
public interface IMember : IContentBase, IMembershipUser
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the Username
|
||||
/// </summary>
|
||||
string Username { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Email
|
||||
/// </summary>
|
||||
string Email { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Password
|
||||
/// </summary>
|
||||
string Password { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Password Question
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Alias: umbracoPasswordRetrievalQuestionPropertyTypeAlias
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
string PasswordQuestion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Password Answer
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Alias: umbracoPasswordRetrievalAnswerPropertyTypeAlias
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
string PasswordAnswer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or set the comments for the member
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Alias: umbracoCommentPropertyTypeAlias
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
string Comments { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the Member is approved
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Alias: umbracoApprovePropertyTypeAlias
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
bool IsApproved { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a boolean indicating whether the Member is locked out
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Alias: umbracoLockPropertyTypeAlias
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
bool IsLockedOut { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the date for last login
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Alias: umbracoLastLoginPropertyTypeAlias
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
DateTime LastLoginDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gest or sets the date for last password change
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Alias: umbracoMemberLastPasswordChange
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
DateTime LastPasswordChangeDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the date for when Member was locked out
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Alias: umbracoMemberLastLockout
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
DateTime LastLockoutDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of failed password attempts.
|
||||
/// This is the number of times the password was entered incorrectly upon login.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Alias: umbracoFailedPasswordAttemptsPropertyTypeAlias
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
int FailedPasswordAttempts { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// String alias of the default ContentType
|
||||
/// </summary>
|
||||
|
||||
@@ -3,7 +3,6 @@ using System.Globalization;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace Umbraco.Core.Models
|
||||
private bool _dontRender;
|
||||
private string _scriptFile;
|
||||
private string _scriptAssembly;
|
||||
private string _python;
|
||||
private string _scriptPath;
|
||||
private string _xslt;
|
||||
private readonly MacroPropertyCollection _properties;
|
||||
private readonly List<string> _addedProperties;
|
||||
@@ -360,14 +360,14 @@ namespace Umbraco.Core.Models
|
||||
[DataMember]
|
||||
public string ScriptPath
|
||||
{
|
||||
get { return _python; }
|
||||
get { return _scriptPath; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_python = value;
|
||||
return _python;
|
||||
}, _python, ScriptPathSelector);
|
||||
_scriptPath = value;
|
||||
return _scriptPath;
|
||||
}, _scriptPath, ScriptPathSelector);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
internal class MacroProperty : TracksChangesEntityBase, IMacroProperty, IRememberBeingDirty
|
||||
public class MacroProperty : TracksChangesEntityBase, IMacroProperty, IRememberBeingDirty
|
||||
{
|
||||
public MacroProperty()
|
||||
{
|
||||
@@ -155,7 +155,6 @@ namespace Umbraco.Core.Models
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
public string EditorAlias
|
||||
|
||||
{
|
||||
get { return _editorAlias; }
|
||||
set
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Umbraco.Core.Models.Mapping
|
||||
/// All automapper configurations are done during startup
|
||||
/// inside an Automapper Initialize call which is better for performance
|
||||
/// </remarks>
|
||||
internal interface IMapperConfiguration : IApplicationEventHandler
|
||||
public interface IMapperConfiguration : IApplicationEventHandler
|
||||
{
|
||||
void ConfigureMappings(IConfiguration config, ApplicationContext applicationContext);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Umbraco.Core.Models.Mapping
|
||||
/// <remarks>
|
||||
/// Use this class if your mapper configuration isn't also explicitly an ApplicationEventHandler.
|
||||
/// </remarks>
|
||||
internal abstract class MapperConfiguration : ApplicationEventHandler, IMapperConfiguration
|
||||
public abstract class MapperConfiguration : ApplicationEventHandler, IMapperConfiguration
|
||||
{
|
||||
public abstract void ConfigureMappings(IConfiguration config, ApplicationContext applicationContext);
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Umbraco.Core.Models
|
||||
_contentType = contentType;
|
||||
}
|
||||
|
||||
public Member(string name, string email, string username, string password, int parentId, IMemberType contentType)
|
||||
internal Member(string name, string email, string username, string password, int parentId, IMemberType contentType)
|
||||
: base(name, parentId, contentType, new PropertyCollection())
|
||||
{
|
||||
Mandate.ParameterNotNull(contentType, "contentType");
|
||||
@@ -42,8 +42,8 @@ namespace Umbraco.Core.Models
|
||||
_password = password;
|
||||
}
|
||||
|
||||
public Member(string name, string email, string username, string password, IContentBase parent, IMemberType contentType)
|
||||
: base(name, parent, contentType, new PropertyCollection())
|
||||
public Member(string name, string email, string username, string password, IMemberType contentType)
|
||||
: this(name, email, username, password, -1, contentType)
|
||||
{
|
||||
Mandate.ParameterNotNull(contentType, "contentType");
|
||||
|
||||
@@ -53,6 +53,17 @@ namespace Umbraco.Core.Models
|
||||
_password = password;
|
||||
}
|
||||
|
||||
//public Member(string name, string email, string username, string password, IContentBase parent, IMemberType contentType)
|
||||
// : base(name, parent, contentType, new PropertyCollection())
|
||||
//{
|
||||
// Mandate.ParameterNotNull(contentType, "contentType");
|
||||
|
||||
// _contentType = contentType;
|
||||
// _email = email;
|
||||
// _username = username;
|
||||
// _password = password;
|
||||
//}
|
||||
|
||||
private static readonly PropertyInfo DefaultContentTypeAliasSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.ContentTypeAlias);
|
||||
private static readonly PropertyInfo UsernameSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.Username);
|
||||
private static readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo<Member, string>(x => x.Email);
|
||||
@@ -377,7 +388,7 @@ namespace Umbraco.Core.Models
|
||||
/// membership provider.
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
internal virtual object ProviderUserKey
|
||||
public virtual object ProviderUserKey
|
||||
{
|
||||
get
|
||||
{
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
//Dictionary is divided into string: PropertyTypeAlias, Tuple: MemberCanEdit, VisibleOnProfile, PropertyTypeId
|
||||
private IDictionary<string, Tuple<bool, bool, int>> _memberTypePropertyTypes;
|
||||
private string _alias;
|
||||
|
||||
public MemberType(int parentId) : base(parentId)
|
||||
{
|
||||
@@ -27,6 +28,29 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
|
||||
private static readonly PropertyInfo MemberTypePropertyTypesSelector = ExpressionHelper.GetPropertyInfo<MemberType, IDictionary<string, Tuple<bool, bool, int>>>(x => x.MemberTypePropertyTypes);
|
||||
private static readonly PropertyInfo AliasSelector = ExpressionHelper.GetPropertyInfo<MemberType, string>(x => x.Alias);
|
||||
|
||||
/// <summary>
|
||||
/// The Alias of the ContentType
|
||||
/// </summary>
|
||||
[DataMember]
|
||||
public override string Alias
|
||||
{
|
||||
get { return _alias; }
|
||||
set
|
||||
{
|
||||
//NOTE: WE are overriding this because we don't want to do a ToSafeAlias when the alias is the special case of
|
||||
// "_umbracoSystemDefaultProtectType" which is used internally, currently there is an issue with the safe alias as it strips
|
||||
// leading underscores which we don't want in this case.
|
||||
// see : http://issues.umbraco.org/issue/U4-3968
|
||||
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_alias = value == "_umbracoSystemDefaultProtectType" ? value : value.ToSafeAlias();
|
||||
return _alias;
|
||||
}, _alias, AliasSelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or Sets a Dictionary of Tuples (MemberCanEdit, VisibleOnProfile, PropertyTypeId) by the PropertyTypes' alias.
|
||||
|
||||
@@ -4,9 +4,9 @@ using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
internal interface IMembershipUser : IMembershipUserId, IAggregateRoot
|
||||
{
|
||||
/*new object Id { get; set; }*/
|
||||
public interface IMembershipUser : IAggregateRoot
|
||||
{
|
||||
object ProviderUserKey { get; set; }
|
||||
string Username { get; set; }
|
||||
string Email { get; set; }
|
||||
string Password { get; set; }
|
||||
@@ -14,13 +14,22 @@ namespace Umbraco.Core.Models.Membership
|
||||
string PasswordAnswer { get; set; }
|
||||
string Comments { get; set; }
|
||||
bool IsApproved { get; set; }
|
||||
bool IsOnline { get; set; }
|
||||
bool IsLockedOut { get; set; }
|
||||
DateTime LastLoginDate { get; set; }
|
||||
DateTime LastPasswordChangeDate { get; set; }
|
||||
DateTime LastLockoutDate { get; set; }
|
||||
|
||||
object ProfileId { get; set; }
|
||||
IEnumerable<object> Groups { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the number of failed password attempts.
|
||||
/// This is the number of times the password was entered incorrectly upon login.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Alias: umbracoFailedPasswordAttemptsPropertyTypeAlias
|
||||
/// Part of the standard properties collection.
|
||||
/// </remarks>
|
||||
int FailedPasswordAttempts { get; set; }
|
||||
|
||||
//object ProfileId { get; set; }
|
||||
//IEnumerable<object> Groups { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
internal interface IMembershipUserId
|
||||
{
|
||||
object ProviderUserKey { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -7,29 +7,28 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// Defines the interface for a <see cref="User"/>
|
||||
/// </summary>
|
||||
/// <remarks>Will be left internal until a proper Membership implementation is part of the roadmap</remarks>
|
||||
internal interface IUser : IMembershipUser, IUserProfile
|
||||
internal interface IUser : IMembershipUser, IProfile
|
||||
{
|
||||
new object Id { get; set; }
|
||||
//string Name { get; set; }
|
||||
|
||||
int SessionTimeout { get; set; }
|
||||
int StartContentId { get; set; }
|
||||
int StartMediaId { get; set; }
|
||||
string Language { get; set; }
|
||||
|
||||
bool NoConsole { get; set; }
|
||||
IUserType UserType { get; }
|
||||
//NOTE: I have removed this because it is obsolete in v7 and we are basically removing live editing for now
|
||||
//bool DefaultToLiveEditing { get; set; }
|
||||
|
||||
IUserType UserType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The default permissions for the user
|
||||
/// The default permission set for the user
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The default permissions are assigned to the user object based on the user type's default permissions
|
||||
/// </remarks>
|
||||
string DefaultPermissions { get; }
|
||||
}
|
||||
/// Currently in umbraco each permission is a single char but with an Enumerable{string} collection this allows for flexible changes to this in the future
|
||||
/// </remarks>
|
||||
IEnumerable<string> DefaultPermissions { get; set; }
|
||||
|
||||
internal interface IUserProfile : IProfile
|
||||
{
|
||||
IEnumerable<string> AllowedSections { get; }
|
||||
void RemoveAllowedSection(string sectionAlias);
|
||||
void AddAllowedSection(string sectionAlias);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
|
||||
@@ -6,8 +7,22 @@ namespace Umbraco.Core.Models.Membership
|
||||
|
||||
internal interface IUserType : IAggregateRoot
|
||||
{
|
||||
/// <summary>
|
||||
/// The user type alias
|
||||
/// </summary>
|
||||
string Alias { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The user type name
|
||||
/// </summary>
|
||||
string Name { get; set; }
|
||||
string Permissions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The set of default permissions for the user type
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future.
|
||||
/// </remarks>
|
||||
IEnumerable<string> Permissions { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -6,15 +6,15 @@ namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
internal static class MembershipExtensions
|
||||
{
|
||||
internal static MembershipUser AsConcreteMembershipUser(this IMember member)
|
||||
internal static UmbracoMembershipMember AsConcreteMembershipUser(this IMembershipUser member, string providerName)
|
||||
{
|
||||
var membershipMember = new UmbracoMembershipMember(member);
|
||||
var membershipMember = new UmbracoMembershipMember(member, providerName);
|
||||
return membershipMember;
|
||||
}
|
||||
|
||||
internal static IMember AsIMember(this MembershipUser membershipMember)
|
||||
internal static IMembershipUser AsIMember(this UmbracoMembershipMember membershipMember)
|
||||
{
|
||||
var member = membershipMember as UmbracoMembershipMember;
|
||||
var member = membershipMember;
|
||||
if (member != null)
|
||||
{
|
||||
return member.Member;
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a Profile which is shared between Members and Users
|
||||
/// </summary>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
internal class Profile : TracksChangesEntityBase, IProfile, IRememberBeingDirty
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Profile"/> class.
|
||||
/// </summary>
|
||||
protected Profile()
|
||||
{
|
||||
ProviderUserKeyType = typeof(int);
|
||||
}
|
||||
|
||||
public Profile(object id, string name)
|
||||
{
|
||||
ProviderUserKeyType = typeof(int);
|
||||
Id = id;
|
||||
Name = name;
|
||||
}
|
||||
|
||||
private object _id;
|
||||
private string _name;
|
||||
private object _providerUserKey;
|
||||
private Type _userTypeKey;
|
||||
|
||||
private static readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo<Profile, object>(x => x.Id);
|
||||
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<Profile, string>(x => x.Name);
|
||||
private static readonly PropertyInfo ProviderUserKeySelector = ExpressionHelper.GetPropertyInfo<Profile, object>(x => x.ProviderUserKey);
|
||||
private static readonly PropertyInfo UserTypeKeySelector = ExpressionHelper.GetPropertyInfo<Profile, Type>(x => x.ProviderUserKeyType);
|
||||
|
||||
[DataMember]
|
||||
public virtual object Id
|
||||
{
|
||||
get
|
||||
{
|
||||
return _id;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_id = value;
|
||||
return _id;
|
||||
}, _id, IdSelector);
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public virtual string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_name = value;
|
||||
return _name;
|
||||
}, _name, NameSelector);
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public virtual object ProviderUserKey
|
||||
{
|
||||
get
|
||||
{
|
||||
return _providerUserKey;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_providerUserKey = value;
|
||||
return _id;
|
||||
}, _providerUserKey, ProviderUserKeySelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the provider user key.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of the provider user key.
|
||||
/// </value>
|
||||
[IgnoreDataMember]
|
||||
internal Type ProviderUserKeyType
|
||||
{
|
||||
get
|
||||
{
|
||||
return _userTypeKey;
|
||||
}
|
||||
private set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_userTypeKey = value;
|
||||
return _userTypeKey;
|
||||
}, _userTypeKey, UserTypeKeySelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the type of the provider user key.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
internal void SetProviderUserKeyType(Type type)
|
||||
{
|
||||
ProviderUserKeyType = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,66 +1,127 @@
|
||||
using System.Web.Security;
|
||||
using System;
|
||||
using System.Web.Security;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
//TODO: THere's still a bunch of properties that don't exist in this use that need to be mapped somehow.
|
||||
|
||||
internal class UmbracoMembershipMember : MembershipUser
|
||||
{
|
||||
private readonly IMember _member;
|
||||
private readonly IMembershipUser _member;
|
||||
private readonly string _userName;
|
||||
private readonly object _providerUserKey;
|
||||
private readonly string _passwordQuestion;
|
||||
private readonly bool _isLockedOut;
|
||||
private readonly DateTime _lastLockoutDate;
|
||||
private readonly DateTime _creationDate;
|
||||
private DateTime _lastLoginDate;
|
||||
private readonly DateTime _lastPasswordChangedDate;
|
||||
private readonly string _providerName;
|
||||
private string _email;
|
||||
private string _comment;
|
||||
private bool _isApproved;
|
||||
private DateTime _lastActivityDate;
|
||||
|
||||
public UmbracoMembershipMember(IMember member)
|
||||
//NOTE: We are only overriding the properties that matter, we don't override things like IsOnline since that is handled with the sub-class and the membership providers.
|
||||
|
||||
//NOTE: We are not calling the base constructor which will validate that a provider with the specified name exists which causes issues with unit tests. The ctor
|
||||
// validation for that doesn't need to be there anyways (have checked the source).
|
||||
public UmbracoMembershipMember(IMembershipUser member, string providerName)
|
||||
{
|
||||
_member = member;
|
||||
//NOTE: We are copying the values here so that everything is consistent with how the underlying built-in ASP.Net membership user
|
||||
// handles data! We don't want to do anything differently there but since we cannot use their ctor we'll need to handle this logic ourselves.
|
||||
if (member.Username != null)
|
||||
_userName = member.Username.Trim();
|
||||
if (member.Email != null)
|
||||
_email = member.Email.Trim();
|
||||
if (member.PasswordQuestion != null)
|
||||
_passwordQuestion = member.PasswordQuestion.Trim();
|
||||
_providerName = providerName;
|
||||
_providerUserKey = member.ProviderUserKey;
|
||||
_comment = member.Comments;
|
||||
_isApproved = member.IsApproved;
|
||||
_isLockedOut = member.IsLockedOut;
|
||||
_creationDate = member.CreateDate.ToUniversalTime();
|
||||
_lastLoginDate = member.LastLoginDate.ToUniversalTime();
|
||||
//TODO: We currently don't really have any place to store this data!!
|
||||
_lastActivityDate = member.LastLoginDate.ToUniversalTime();
|
||||
_lastPasswordChangedDate = member.LastPasswordChangeDate.ToUniversalTime();
|
||||
_lastLockoutDate = member.LastLockoutDate.ToUniversalTime();
|
||||
}
|
||||
|
||||
internal IMember Member
|
||||
|
||||
internal IMembershipUser Member
|
||||
{
|
||||
get { return _member; }
|
||||
}
|
||||
|
||||
public override string Email
|
||||
public override string UserName
|
||||
{
|
||||
get { return _member.Email; }
|
||||
set { _member.Email = value; }
|
||||
get { return _userName; }
|
||||
}
|
||||
|
||||
public override object ProviderUserKey
|
||||
{
|
||||
get { return _member.Key; }
|
||||
get { return _providerUserKey; }
|
||||
}
|
||||
|
||||
public override System.DateTime CreationDate
|
||||
public override string Email
|
||||
{
|
||||
get { return _member.CreateDate; }
|
||||
get { return _email; }
|
||||
set { _email = value; }
|
||||
}
|
||||
|
||||
public override string UserName
|
||||
public override string PasswordQuestion
|
||||
{
|
||||
get { return _member.Username; }
|
||||
get { return _passwordQuestion; }
|
||||
}
|
||||
|
||||
public override string Comment
|
||||
{
|
||||
get { return _member.Comments; }
|
||||
set { _member.Comments = value; }
|
||||
get { return _comment; }
|
||||
set { _comment = value; }
|
||||
}
|
||||
|
||||
public override bool IsApproved
|
||||
{
|
||||
get { return _member.IsApproved; }
|
||||
set { _member.IsApproved = value; }
|
||||
get { return _isApproved; }
|
||||
set { _isApproved = value; }
|
||||
}
|
||||
|
||||
public override bool IsLockedOut
|
||||
{
|
||||
get { return _member.IsLockedOut; }
|
||||
get { return _isLockedOut; }
|
||||
}
|
||||
|
||||
public override System.DateTime LastLoginDate
|
||||
public override DateTime LastLockoutDate
|
||||
{
|
||||
get { return _member.LastLoginDate; }
|
||||
set { _member.LastLoginDate = value; }
|
||||
get { return _lastLockoutDate; }
|
||||
}
|
||||
|
||||
public override DateTime CreationDate
|
||||
{
|
||||
get { return _creationDate; }
|
||||
}
|
||||
|
||||
public override DateTime LastLoginDate
|
||||
{
|
||||
get { return _lastLoginDate; }
|
||||
set { _lastLoginDate = value; }
|
||||
}
|
||||
|
||||
public override DateTime LastActivityDate
|
||||
{
|
||||
get { return _lastActivityDate; }
|
||||
set { _lastActivityDate = value; }
|
||||
}
|
||||
|
||||
public override DateTime LastPasswordChangedDate
|
||||
{
|
||||
get { return _lastPasswordChangedDate; }
|
||||
}
|
||||
|
||||
public override string ProviderName
|
||||
{
|
||||
get { return _providerName; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
@@ -16,15 +19,69 @@ namespace Umbraco.Core.Models.Membership
|
||||
/// </remarks>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
internal class User : UserProfile, IUser
|
||||
internal class User : TracksChangesEntityBase, IUser
|
||||
{
|
||||
private bool _hasIdentity;
|
||||
|
||||
public User(IUserType userType)
|
||||
{
|
||||
Groups = new List<object> { userType };
|
||||
if (userType == null) throw new ArgumentNullException("userType");
|
||||
|
||||
_userType = userType;
|
||||
//Groups = new List<object> { userType };
|
||||
SessionTimeout = 60;
|
||||
_sectionCollection = new ObservableCollection<string>();
|
||||
_addedSections = new List<string>();
|
||||
_removedSections = new List<string>();
|
||||
_sectionCollection.CollectionChanged += SectionCollectionChanged;
|
||||
}
|
||||
|
||||
public User(string name, string email, string username, string password, IUserType userType)
|
||||
: this(userType)
|
||||
{
|
||||
_name = name;
|
||||
_email = email;
|
||||
_username = username;
|
||||
_password = password;
|
||||
}
|
||||
|
||||
private readonly IUserType _userType;
|
||||
private bool _hasIdentity;
|
||||
private object _id;
|
||||
private string _name;
|
||||
private Type _userTypeKey;
|
||||
private readonly List<string> _addedSections;
|
||||
private readonly List<string> _removedSections;
|
||||
private readonly ObservableCollection<string> _sectionCollection;
|
||||
private int _sessionTimeout;
|
||||
private int _startContentId;
|
||||
private int _startMediaId;
|
||||
|
||||
private string _username;
|
||||
private string _email;
|
||||
private string _password;
|
||||
private Guid _key;
|
||||
private bool _isApproved;
|
||||
private bool _isLockedOut;
|
||||
private string _language;
|
||||
private IEnumerable<string> _defaultPermissions;
|
||||
private bool _defaultToLiveEditing;
|
||||
|
||||
private static readonly PropertyInfo SessionTimeoutSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.SessionTimeout);
|
||||
private static readonly PropertyInfo StartContentIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartContentId);
|
||||
private static readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo<User, int>(x => x.StartMediaId);
|
||||
private static readonly PropertyInfo AllowedSectionsSelector = ExpressionHelper.GetPropertyInfo<User, IEnumerable<string>>(x => x.AllowedSections);
|
||||
private static readonly PropertyInfo IdSelector = ExpressionHelper.GetPropertyInfo<User, object>(x => x.Id);
|
||||
private static readonly PropertyInfo NameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Name);
|
||||
private static readonly PropertyInfo UserTypeKeySelector = ExpressionHelper.GetPropertyInfo<User, Type>(x => x.ProviderUserKeyType);
|
||||
|
||||
private static readonly PropertyInfo UsernameSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Username);
|
||||
private static readonly PropertyInfo EmailSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Email);
|
||||
private static readonly PropertyInfo PasswordSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Password);
|
||||
private static readonly PropertyInfo IsLockedOutSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.IsLockedOut);
|
||||
private static readonly PropertyInfo IsApprovedSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.IsApproved);
|
||||
private static readonly PropertyInfo LanguageSelector = ExpressionHelper.GetPropertyInfo<User, string>(x => x.Language);
|
||||
private static readonly PropertyInfo DefaultPermissionsSelector = ExpressionHelper.GetPropertyInfo<User, IEnumerable<string>>(x => x.DefaultPermissions);
|
||||
private static readonly PropertyInfo DefaultToLiveEditingSelector = ExpressionHelper.GetPropertyInfo<User, bool>(x => x.DefaultToLiveEditing);
|
||||
|
||||
#region Implementation of IEntity
|
||||
|
||||
[IgnoreDataMember]
|
||||
@@ -35,78 +92,372 @@ namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
get
|
||||
{
|
||||
return int.Parse(base.Id.ToString());
|
||||
return int.Parse(Id.ToString());
|
||||
}
|
||||
set
|
||||
{
|
||||
base.Id = value;
|
||||
Id = value;
|
||||
_hasIdentity = true;
|
||||
}
|
||||
}
|
||||
|
||||
//this doesn't get used
|
||||
[IgnoreDataMember]
|
||||
public Guid Key { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IMembershipUser
|
||||
|
||||
[DataMember]
|
||||
public string Username { get; set; }
|
||||
[DataMember]
|
||||
public string Email { get; set; }
|
||||
[DataMember]
|
||||
public string Password { get; set; }
|
||||
[DataMember]
|
||||
public string PasswordQuestion { get; set; }
|
||||
[DataMember]
|
||||
public string PasswordAnswer { get; set; }
|
||||
[DataMember]
|
||||
public string Comments { get; set; }
|
||||
[DataMember]
|
||||
public bool IsApproved { get; set; }
|
||||
[DataMember]
|
||||
public bool IsOnline { get; set; }
|
||||
[DataMember]
|
||||
public bool IsLockedOut { get; set; }
|
||||
[DataMember]
|
||||
public DateTime CreateDate { get; set; }
|
||||
[DataMember]
|
||||
public DateTime UpdateDate { get; set; }
|
||||
[DataMember]
|
||||
public DateTime LastLoginDate { get; set; }
|
||||
[DataMember]
|
||||
public DateTime LastPasswordChangeDate { get; set; }
|
||||
[DataMember]
|
||||
public DateTime LastLockoutDate { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public object ProviderUserKey
|
||||
{
|
||||
get { return Id; }
|
||||
set { throw new NotSupportedException("Cannot set the provider user key for a user"); }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the type of the provider user key.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The type of the provider user key.
|
||||
/// </value>
|
||||
[IgnoreDataMember]
|
||||
internal Type ProviderUserKeyType
|
||||
{
|
||||
get
|
||||
{
|
||||
return _userTypeKey;
|
||||
}
|
||||
private set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_userTypeKey = value;
|
||||
return _userTypeKey;
|
||||
}, _userTypeKey, UserTypeKeySelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets the type of the provider user key.
|
||||
/// </summary>
|
||||
/// <param name="type">The type.</param>
|
||||
internal void SetProviderUserKeyType(Type type)
|
||||
{
|
||||
ProviderUserKeyType = type;
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public object ProfileId { get; set; }
|
||||
public string Username
|
||||
{
|
||||
get { return _username; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_username = value;
|
||||
return _username;
|
||||
}, _username, UsernameSelector);
|
||||
}
|
||||
}
|
||||
[DataMember]
|
||||
public IEnumerable<object> Groups { get; set; }
|
||||
public string Email
|
||||
{
|
||||
get { return _email; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_email = value;
|
||||
return _email;
|
||||
}, _email, EmailSelector);
|
||||
}
|
||||
}
|
||||
[DataMember]
|
||||
public string Password
|
||||
{
|
||||
get { return _password; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_password = value;
|
||||
return _password;
|
||||
}, _password, PasswordSelector);
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public bool IsApproved
|
||||
{
|
||||
get { return _isApproved; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_isApproved = value;
|
||||
return _isApproved;
|
||||
}, _isApproved, IsApprovedSelector);
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public bool IsLockedOut
|
||||
{
|
||||
get { return _isLockedOut; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_isLockedOut = value;
|
||||
return _isLockedOut;
|
||||
}, _isLockedOut, IsLockedOutSelector);
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: Figure out how to support all of this! - we cannot have NotImplementedExceptions because these get used by the IMembershipMemberService<IUser> service so
|
||||
// we'll just have them as generic get/set which don't interact with the db.
|
||||
|
||||
[IgnoreDataMember]
|
||||
public string PasswordQuestion { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public string PasswordAnswer { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public string Comments { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public DateTime CreateDate { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public DateTime UpdateDate { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public DateTime LastLoginDate { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public DateTime LastPasswordChangeDate { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public DateTime LastLockoutDate { get; set; }
|
||||
[IgnoreDataMember]
|
||||
public int FailedPasswordAttempts { get; set; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IProfile
|
||||
|
||||
[DataMember]
|
||||
public string Name
|
||||
{
|
||||
get { return _name; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_name = value;
|
||||
return _name;
|
||||
}, _name, NameSelector);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IUser
|
||||
|
||||
public IEnumerable<string> AllowedSections
|
||||
{
|
||||
get { return _sectionCollection; }
|
||||
}
|
||||
|
||||
public void RemoveAllowedSection(string sectionAlias)
|
||||
{
|
||||
_sectionCollection.Remove(sectionAlias);
|
||||
}
|
||||
|
||||
public void AddAllowedSection(string sectionAlias)
|
||||
{
|
||||
if (_sectionCollection.Contains(sectionAlias) == false)
|
||||
{
|
||||
_sectionCollection.Add(sectionAlias);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to check if we need to add a section in the repository to the db
|
||||
/// </summary>
|
||||
internal IEnumerable<string> AddedSections
|
||||
{
|
||||
get { return _addedSections; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to check if we need to remove a section in the repository to the db
|
||||
/// </summary>
|
||||
internal IEnumerable<string> RemovedSections
|
||||
{
|
||||
get { return _removedSections; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the session timeout.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The session timeout.
|
||||
/// </value>
|
||||
[DataMember]
|
||||
public string Language { get; set; }
|
||||
public int SessionTimeout
|
||||
{
|
||||
get { return _sessionTimeout; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_sessionTimeout = value;
|
||||
return _sessionTimeout;
|
||||
}, _sessionTimeout, SessionTimeoutSelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start content id.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The start content id.
|
||||
/// </value>
|
||||
[DataMember]
|
||||
public int StartContentId
|
||||
{
|
||||
get { return _startContentId; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_startContentId = value;
|
||||
return _startContentId;
|
||||
}, _startContentId, StartContentIdSelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start media id.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The start media id.
|
||||
/// </value>
|
||||
[DataMember]
|
||||
public int StartMediaId
|
||||
{
|
||||
get { return _startMediaId; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_startMediaId = value;
|
||||
return _startMediaId;
|
||||
}, _startMediaId, StartMediaIdSelector);
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public string DefaultPermissions { get; set; }
|
||||
public object Id
|
||||
{
|
||||
get { return _id; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_id = value;
|
||||
return _id;
|
||||
}, _id, IdSelector);
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public bool NoConsole { get; set; }
|
||||
public string Language
|
||||
{
|
||||
get { return _language; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_language = value;
|
||||
return _language;
|
||||
}, _language, LanguageSelector);
|
||||
}
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public IEnumerable<string> DefaultPermissions
|
||||
{
|
||||
get { return _defaultPermissions; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_defaultPermissions = value;
|
||||
return _defaultPermissions;
|
||||
}, _defaultPermissions, DefaultPermissionsSelector);
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
internal bool DefaultToLiveEditing
|
||||
{
|
||||
get { return _defaultToLiveEditing; }
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_defaultToLiveEditing = value;
|
||||
return _defaultToLiveEditing;
|
||||
}, _defaultToLiveEditing, DefaultToLiveEditingSelector);
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public IUserType UserType
|
||||
{
|
||||
get
|
||||
{
|
||||
var type = Groups.FirstOrDefault();
|
||||
return type as IUserType;
|
||||
}
|
||||
get { return _userType; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Whenever resetting occurs, clear the remembered add/removed collections, even if
|
||||
/// rememberPreviouslyChangedProperties is true, the AllowedSections property will still
|
||||
/// be flagged as dirty.
|
||||
/// </summary>
|
||||
/// <param name="rememberPreviouslyChangedProperties"></param>
|
||||
public override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
|
||||
{
|
||||
_addedSections.Clear();
|
||||
_removedSections.Clear();
|
||||
base.ResetDirtyProperties(rememberPreviouslyChangedProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the collection changed event in order for us to flag the AllowedSections property as changed
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void SectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(AllowedSectionsSelector);
|
||||
|
||||
if (e.Action == NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
//remove from the removed/added sections (since people could add/remove all they want in one request)
|
||||
_removedSections.RemoveAll(s => s == e.NewItems.Cast<string>().First());
|
||||
_addedSections.RemoveAll(s => s == e.NewItems.Cast<string>().First());
|
||||
|
||||
//add to the added sections
|
||||
_addedSections.Add(e.NewItems.Cast<string>().First());
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Remove)
|
||||
{
|
||||
//remove from the removed/added sections (since people could add/remove all they want in one request)
|
||||
_removedSections.RemoveAll(s => s == e.OldItems.Cast<string>().First());
|
||||
_addedSections.RemoveAll(s => s == e.OldItems.Cast<string>().First());
|
||||
|
||||
//add to the added sections
|
||||
_removedSections.Add(e.OldItems.Cast<string>().First());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,188 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Models.Membership
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the Profile implementation for a backoffice User
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Should be internal until a proper user/membership implementation
|
||||
/// is part of the roadmap.
|
||||
/// </remarks>
|
||||
[Serializable]
|
||||
[DataContract(IsReference = true)]
|
||||
internal class UserProfile : Profile, IUserProfile
|
||||
{
|
||||
public UserProfile()
|
||||
{
|
||||
SessionTimeout = 60;
|
||||
_sectionCollection = new ObservableCollection<string>();
|
||||
_addedSections = new List<string>();
|
||||
_removedSections = new List<string>();
|
||||
_sectionCollection.CollectionChanged += SectionCollectionChanged;
|
||||
}
|
||||
|
||||
private readonly List<string> _addedSections;
|
||||
private readonly List<string> _removedSections;
|
||||
private readonly ObservableCollection<string> _sectionCollection;
|
||||
private int _sessionTimeout;
|
||||
private int _startContentId;
|
||||
private int _startMediaId;
|
||||
|
||||
private static readonly PropertyInfo SessionTimeoutSelector = ExpressionHelper.GetPropertyInfo<UserProfile, int>(x => x.SessionTimeout);
|
||||
private static readonly PropertyInfo StartContentIdSelector = ExpressionHelper.GetPropertyInfo<UserProfile, int>(x => x.StartContentId);
|
||||
private static readonly PropertyInfo StartMediaIdSelector = ExpressionHelper.GetPropertyInfo<UserProfile, int>(x => x.StartMediaId);
|
||||
private static readonly PropertyInfo AllowedSectionsSelector = ExpressionHelper.GetPropertyInfo<UserProfile, IEnumerable<string>>(x => x.AllowedSections);
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the session timeout.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The session timeout.
|
||||
/// </value>
|
||||
[DataMember]
|
||||
public int SessionTimeout
|
||||
{
|
||||
get
|
||||
{
|
||||
return _sessionTimeout;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_sessionTimeout = value;
|
||||
return _sessionTimeout;
|
||||
}, _sessionTimeout, SessionTimeoutSelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start content id.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The start content id.
|
||||
/// </value>
|
||||
[DataMember]
|
||||
public int StartContentId
|
||||
{
|
||||
get
|
||||
{
|
||||
return _startContentId;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_startContentId = value;
|
||||
return _startContentId;
|
||||
}, _startContentId, StartContentIdSelector);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the start media id.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The start media id.
|
||||
/// </value>
|
||||
[DataMember]
|
||||
public int StartMediaId
|
||||
{
|
||||
get
|
||||
{
|
||||
return _startMediaId;
|
||||
}
|
||||
set
|
||||
{
|
||||
SetPropertyValueAndDetectChanges(o =>
|
||||
{
|
||||
_startMediaId = value;
|
||||
return _startMediaId;
|
||||
}, _startMediaId, StartMediaIdSelector);
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<string> AllowedSections
|
||||
{
|
||||
get { return _sectionCollection; }
|
||||
}
|
||||
|
||||
public void RemoveAllowedSection(string sectionAlias)
|
||||
{
|
||||
_sectionCollection.Remove(sectionAlias);
|
||||
}
|
||||
|
||||
public void AddAllowedSection(string sectionAlias)
|
||||
{
|
||||
if (!_sectionCollection.Contains(sectionAlias))
|
||||
{
|
||||
_sectionCollection.Add(sectionAlias);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whenever resetting occurs, clear the remembered add/removed collections, even if
|
||||
/// rememberPreviouslyChangedProperties is true, the AllowedSections property will still
|
||||
/// be flagged as dirty.
|
||||
/// </summary>
|
||||
/// <param name="rememberPreviouslyChangedProperties"></param>
|
||||
public override void ResetDirtyProperties(bool rememberPreviouslyChangedProperties)
|
||||
{
|
||||
_addedSections.Clear();
|
||||
_removedSections.Clear();
|
||||
base.ResetDirtyProperties(rememberPreviouslyChangedProperties);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to check if we need to add a section in the repository to the db
|
||||
/// </summary>
|
||||
internal IEnumerable<string> AddedSections
|
||||
{
|
||||
get { return _addedSections; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used internally to check if we need to remove a section in the repository to the db
|
||||
/// </summary>
|
||||
internal IEnumerable<string> RemovedSections
|
||||
{
|
||||
get { return _removedSections; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Handles the collection changed event in order for us to flag the AllowedSections property as changed
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void SectionCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
OnPropertyChanged(AllowedSectionsSelector);
|
||||
|
||||
if (e.Action == NotifyCollectionChangedAction.Add)
|
||||
{
|
||||
//remove from the removed/added sections (since people could add/remove all they want in one request)
|
||||
_removedSections.RemoveAll(s => s == e.NewItems.Cast<string>().First());
|
||||
_addedSections.RemoveAll(s => s == e.NewItems.Cast<string>().First());
|
||||
|
||||
//add to the added sections
|
||||
_addedSections.Add(e.NewItems.Cast<string>().First());
|
||||
}
|
||||
else if (e.Action == NotifyCollectionChangedAction.Remove)
|
||||
{
|
||||
//remove from the removed/added sections (since people could add/remove all they want in one request)
|
||||
_removedSections.RemoveAll(s => s == e.OldItems.Cast<string>().First());
|
||||
_addedSections.RemoveAll(s => s == e.OldItems.Cast<string>().First());
|
||||
|
||||
//add to the added sections
|
||||
_removedSections.Add(e.OldItems.Cast<string>().First());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
@@ -22,7 +23,13 @@ namespace Umbraco.Core.Models.Membership
|
||||
[DataMember]
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The set of default permissions for the user type
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// By default each permission is simply a single char but we've made this an enumerable{string} to support a more flexible permissions structure in the future.
|
||||
/// </remarks>
|
||||
[DataMember]
|
||||
public string Permissions { get; set; }
|
||||
public IEnumerable<string> Permissions { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
internal class Notification
|
||||
{
|
||||
public Notification(int entityId, int userId, string action, Guid entityType)
|
||||
{
|
||||
EntityId = entityId;
|
||||
UserId = userId;
|
||||
Action = action;
|
||||
EntityType = entityType;
|
||||
}
|
||||
|
||||
public int EntityId { get; private set; }
|
||||
public int UserId { get; private set; }
|
||||
public string Action { get; private set; }
|
||||
public Guid EntityType { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -377,8 +377,16 @@ namespace Umbraco.Core.Models
|
||||
//Check against Regular Expression for Legacy DataTypes - Validation exists and value is not null:
|
||||
if(string.IsNullOrEmpty(ValidationRegExp) == false && (value != null && string.IsNullOrEmpty(value.ToString()) == false))
|
||||
{
|
||||
var regexPattern = new Regex(ValidationRegExp);
|
||||
return regexPattern.IsMatch(value.ToString());
|
||||
try
|
||||
{
|
||||
var regexPattern = new Regex(ValidationRegExp);
|
||||
return regexPattern.IsMatch(value.ToString());
|
||||
}
|
||||
catch
|
||||
{
|
||||
throw new Exception(string .Format("Invalid validation expression on property {0}",this.Alias));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//TODO Add PropertyEditor validation when its relevant to introduce
|
||||
|
||||
@@ -80,11 +80,8 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
|
||||
private void InitializeConverters()
|
||||
{
|
||||
var converters = PropertyValueConvertersResolver.Current.Converters.ToArray();
|
||||
|
||||
var defaultConverters = converters
|
||||
.Where(x => x.GetType().GetCustomAttribute<DefaultPropertyValueConverterAttribute>(false) != null)
|
||||
.ToArray();
|
||||
var converters = PropertyValueConvertersResolver.Current.Converters.ToArray();
|
||||
var defaultConvertersWithAttributes = PropertyValueConvertersResolver.Current.DefaultConverters;
|
||||
|
||||
_converter = null;
|
||||
|
||||
@@ -98,8 +95,14 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
else if (foundConverters.Length > 1)
|
||||
{
|
||||
//more than one was found, we need to first figure out if one of these is an Umbraco default value type converter
|
||||
var nonDefault = foundConverters.Except(defaultConverters).ToArray();
|
||||
if (nonDefault.Length > 1)
|
||||
//get the non-default and see if we have one
|
||||
var nonDefault = foundConverters.Except(defaultConvertersWithAttributes.Select(x => x.Item1)).ToArray();
|
||||
if (nonDefault.Length == 1)
|
||||
{
|
||||
//there's only 1 custom converter registered that so use it
|
||||
_converter = nonDefault[0];
|
||||
}
|
||||
else if (nonDefault.Length > 1)
|
||||
{
|
||||
//this is not allowed, there cannot be more than 1 custom converter
|
||||
throw new InvalidOperationException(
|
||||
@@ -109,9 +112,31 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
ContentType.Alias, PropertyTypeAlias,
|
||||
nonDefault[1].GetType().FullName, nonDefault[0].GetType().FullName));
|
||||
}
|
||||
else
|
||||
{
|
||||
//we need to remove any converters that have been shadowed by another converter
|
||||
var foundDefaultConvertersWithAttributes = defaultConvertersWithAttributes.Where(x => foundConverters.Contains(x.Item1));
|
||||
var shadowedTypes = foundDefaultConvertersWithAttributes.SelectMany(x => x.Item2.DefaultConvertersToShadow);
|
||||
var shadowedDefaultConverters = foundConverters.Where(x => shadowedTypes.Contains(x.GetType()));
|
||||
var nonShadowedDefaultConverters = foundConverters.Except(shadowedDefaultConverters).ToArray();
|
||||
|
||||
//there's only 1 custom converter registered that so use it
|
||||
_converter = nonDefault[0];
|
||||
if (nonShadowedDefaultConverters.Length == 1)
|
||||
{
|
||||
//assign to the single default converter
|
||||
_converter = nonShadowedDefaultConverters[0];
|
||||
}
|
||||
else if (nonShadowedDefaultConverters.Length > 1)
|
||||
{
|
||||
//this is not allowed, there cannot be more than 1 custom converter
|
||||
throw new InvalidOperationException(
|
||||
string.Format("Type '{2}' cannot be an IPropertyValueConverter"
|
||||
+ " for property '{1}' of content type '{0}' because type '{3}' has already been detected as a converter"
|
||||
+ " for that property, and only one converter can exist for a property.",
|
||||
ContentType.Alias, PropertyTypeAlias,
|
||||
nonShadowedDefaultConverters[1].GetType().FullName, nonShadowedDefaultConverters[0].GetType().FullName));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// get the cache levels, quietely fixing the inconsistencies (no need to throw, really)
|
||||
|
||||
@@ -30,7 +30,6 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
public DateTime DateRegistered { get; set; }
|
||||
|
||||
[Column("lastNotifiedDate")]
|
||||
[Constraint(Default = "getdate()")]
|
||||
public DateTime LastNotified { get; set; }
|
||||
|
||||
[Column("isActive")]
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web.UI.WebControls;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
internal static class UmbracoEntityExtensions
|
||||
{
|
||||
|
||||
public static object GetAdditionalDataValueIgnoreCase(this IUmbracoEntity entity, string key, object defaultVal)
|
||||
{
|
||||
if (entity.AdditionalData.ContainsKeyIgnoreCase(key) == false) return defaultVal;
|
||||
return entity.AdditionalData.GetValueIgnoreCase(key, defaultVal);
|
||||
}
|
||||
|
||||
public static bool IsContainer(this IUmbracoEntity entity)
|
||||
{
|
||||
if (entity.AdditionalData.ContainsKeyIgnoreCase("IsContainer") == false) return false;
|
||||
var val = entity.AdditionalData.GetValueIgnoreCase("IsContainer", null);
|
||||
if (val is bool && (bool) val)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -151,6 +151,21 @@ namespace Umbraco.Core.Persistence.Caching
|
||||
_keyTracker.Remove(key);
|
||||
}
|
||||
|
||||
public void Delete(Type type, int entityId)
|
||||
{
|
||||
var key = GetCompositeId(type, entityId);
|
||||
if (_memoryCache != null)
|
||||
{
|
||||
_memoryCache.Remove(key);
|
||||
}
|
||||
else
|
||||
{
|
||||
HttpRuntime.Cache.Remove(key);
|
||||
}
|
||||
|
||||
_keyTracker.Remove(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear cache by type
|
||||
/// </summary>
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
CreateDate = dto.CreateDate,
|
||||
UpdateDate = dto.UpdateDate,
|
||||
Name = dto.Text,
|
||||
ProviderUserKey = dto.UniqueId,
|
||||
ProviderUserKey = dto.UniqueId.Value,
|
||||
Trashed = dto.Trashed,
|
||||
Key = dto.UniqueId.Value,
|
||||
CreatorId = dto.UserId.HasValue ? dto.UserId.Value : 0,
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
|
||||
var propertyTypes = GetPropertyTypes(dto, memberType);
|
||||
//By Convention we add 9 stnd PropertyTypes - This is only here to support loading of types that didn't have these conventions before.
|
||||
var standardPropertyTypes = Constants.Conventions.Member.StandardPropertyTypeStubs;
|
||||
var standardPropertyTypes = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
|
||||
foreach (var standardPropertyType in standardPropertyTypes)
|
||||
{
|
||||
if(dto.PropertyTypes.Any(x => x.Alias.Equals(standardPropertyType.Key))) continue;
|
||||
|
||||
@@ -17,12 +17,12 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
public IRelation BuildEntity(RelationDto dto)
|
||||
{
|
||||
var entity = new Relation(dto.ParentId, dto.ChildId, _relationType)
|
||||
{
|
||||
Comment = dto.Comment,
|
||||
CreateDate = dto.Datetime,
|
||||
Id = dto.Id,
|
||||
UpdateDate = dto.Datetime
|
||||
};
|
||||
{
|
||||
Comment = dto.Comment,
|
||||
CreateDate = dto.Datetime,
|
||||
Id = dto.Id,
|
||||
UpdateDate = dto.Datetime
|
||||
};
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
entity.ResetDirtyProperties(false);
|
||||
@@ -32,13 +32,13 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
public RelationDto BuildDto(IRelation entity)
|
||||
{
|
||||
var dto = new RelationDto
|
||||
{
|
||||
ChildId = entity.ChildId,
|
||||
Comment = string.IsNullOrEmpty(entity.Comment) ? string.Empty : entity.Comment,
|
||||
Datetime = entity.CreateDate,
|
||||
ParentId = entity.ParentId,
|
||||
RelationType = entity.RelationType.Id
|
||||
};
|
||||
{
|
||||
ChildId = entity.ChildId,
|
||||
Comment = string.IsNullOrEmpty(entity.Comment) ? string.Empty : entity.Comment,
|
||||
Datetime = entity.CreateDate,
|
||||
ParentId = entity.ParentId,
|
||||
RelationType = entity.RelationType.Id
|
||||
};
|
||||
|
||||
if (entity.HasIdentity)
|
||||
dto.Id = entity.Id;
|
||||
|
||||
@@ -10,11 +10,11 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
public IRelationType BuildEntity(RelationTypeDto dto)
|
||||
{
|
||||
var entity = new RelationType(dto.ChildObjectType, dto.ParentObjectType, dto.Alias)
|
||||
{
|
||||
Id = dto.Id,
|
||||
IsBidirectional = dto.Dual,
|
||||
Name = dto.Name
|
||||
};
|
||||
{
|
||||
Id = dto.Id,
|
||||
IsBidirectional = dto.Dual,
|
||||
Name = dto.Name
|
||||
};
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
entity.ResetDirtyProperties(false);
|
||||
@@ -24,14 +24,14 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
public RelationTypeDto BuildDto(IRelationType entity)
|
||||
{
|
||||
var dto = new RelationTypeDto
|
||||
{
|
||||
Alias = entity.Alias,
|
||||
ChildObjectType = entity.ChildObjectType,
|
||||
Dual = entity.IsBidirectional,
|
||||
Name = entity.Name,
|
||||
ParentObjectType = entity.ParentObjectType
|
||||
};
|
||||
if(entity.HasIdentity)
|
||||
{
|
||||
Alias = entity.Alias,
|
||||
ChildObjectType = entity.ChildObjectType,
|
||||
Dual = entity.IsBidirectional,
|
||||
Name = entity.Name,
|
||||
ParentObjectType = entity.ParentObjectType
|
||||
};
|
||||
if (entity.HasIdentity)
|
||||
dto.Id = entity.Id;
|
||||
|
||||
return dto;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
@@ -18,24 +19,23 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
|
||||
public IUser BuildEntity(UserDto dto)
|
||||
{
|
||||
var guidId = dto.Id.ToGuid();
|
||||
var user = new User(_userType)
|
||||
{
|
||||
Id = dto.Id,
|
||||
ProfileId = dto.Id,
|
||||
StartContentId = dto.ContentStartId,
|
||||
StartMediaId = dto.MediaStartId.HasValue ? dto.MediaStartId.Value : -1,
|
||||
Password = dto.Password,
|
||||
Username = dto.Login,
|
||||
Name = dto.UserName,
|
||||
IsLockedOut = dto.Disabled,
|
||||
IsApproved = dto.Disabled == false,
|
||||
Email = dto.Email,
|
||||
Language = dto.UserLanguage,
|
||||
NoConsole = dto.NoConsole,
|
||||
|
||||
//NOTE: The default permission come from the user type's default permissions
|
||||
DefaultPermissions = _userType.Permissions
|
||||
};
|
||||
{
|
||||
Id = dto.Id,
|
||||
Key = guidId,
|
||||
StartContentId = dto.ContentStartId,
|
||||
StartMediaId = dto.MediaStartId.HasValue ? dto.MediaStartId.Value : -1,
|
||||
Password = dto.Password,
|
||||
Username = dto.Login,
|
||||
Name = dto.UserName,
|
||||
IsLockedOut = dto.NoConsole,
|
||||
IsApproved = dto.Disabled == false,
|
||||
Email = dto.Email,
|
||||
Language = dto.UserLanguage,
|
||||
//NOTE: The default permission come from the user type's default permissions
|
||||
DefaultPermissions = _userType.Permissions
|
||||
};
|
||||
|
||||
foreach (var app in dto.User2AppDtos)
|
||||
{
|
||||
@@ -58,7 +58,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
Disabled = entity.IsApproved == false,
|
||||
Email = entity.Email,
|
||||
Login = entity.Username,
|
||||
NoConsole = entity.NoConsole,
|
||||
NoConsole = entity.IsLockedOut,
|
||||
Password = entity.Password,
|
||||
UserLanguage = entity.Language,
|
||||
UserName = entity.Name,
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Factories
|
||||
@@ -10,12 +12,14 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
public IUserType BuildEntity(UserTypeDto dto)
|
||||
{
|
||||
var userType = new UserType
|
||||
{
|
||||
Alias = dto.Alias,
|
||||
Id = dto.Id,
|
||||
Name = dto.Name,
|
||||
Permissions = dto.DefaultPermissions
|
||||
};
|
||||
{
|
||||
Alias = dto.Alias,
|
||||
Id = dto.Id,
|
||||
Name = dto.Name,
|
||||
Permissions = dto.DefaultPermissions.IsNullOrWhiteSpace()
|
||||
? Enumerable.Empty<string>()
|
||||
: dto.DefaultPermissions.ToCharArray().Select(x => x.ToString(CultureInfo.InvariantCulture))
|
||||
};
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
userType.ResetDirtyProperties(false);
|
||||
@@ -27,7 +31,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
var userType = new UserTypeDto
|
||||
{
|
||||
Alias = entity.Alias,
|
||||
DefaultPermissions = entity.Permissions,
|
||||
DefaultPermissions = entity.Permissions == null ? "" : string.Join("", entity.Permissions),
|
||||
Name = entity.Name
|
||||
};
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<Relation, RelationDto>(src => src.ParentId, dto => dto.ParentId);
|
||||
CacheMap<Relation, RelationDto>(src => src.RelationTypeId, dto => dto.RelationType);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<RelationType, RelationTypeDto>(src => src.Name, dto => dto.Name);
|
||||
CacheMap<RelationType, RelationTypeDto>(src => src.ParentObjectType, dto => dto.ParentObjectType);
|
||||
}
|
||||
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -38,7 +38,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
CacheMap<User, UserDto>(src => src.StartMediaId, dto => dto.MediaStartId);
|
||||
CacheMap<User, UserDto>(src => src.StartContentId, dto => dto.ContentStartId);
|
||||
CacheMap<User, UserDto>(src => src.IsApproved, dto => dto.Disabled);
|
||||
CacheMap<User, UserDto>(src => src.NoConsole, dto => dto.NoConsole);
|
||||
CacheMap<User, UserDto>(src => src.IsLockedOut, dto => dto.NoConsole);
|
||||
CacheMap<User, UserDto>(src => src.UserType, dto => dto.Type);
|
||||
CacheMap<User, UserDto>(src => src.Language, dto => dto.UserLanguage);
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete
|
||||
|
||||
public IDeleteColumnFromTableSyntax Column(string columnName)
|
||||
{
|
||||
var expression = _databaseProviders == null
|
||||
var expression = _databaseProviders == null
|
||||
? new DeleteColumnExpression { ColumnNames = { columnName } }
|
||||
: new DeleteColumnExpression(_context.CurrentDatabaseProvider, _databaseProviders) { ColumnNames = { columnName } };
|
||||
_context.Expressions.Add(expression);
|
||||
@@ -36,7 +36,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete
|
||||
|
||||
public IDeleteForeignKeyFromTableSyntax ForeignKey()
|
||||
{
|
||||
var expression = _databaseProviders == null
|
||||
var expression = _databaseProviders == null
|
||||
? new DeleteForeignKeyExpression()
|
||||
: new DeleteForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders);
|
||||
_context.Expressions.Add(expression);
|
||||
@@ -45,7 +45,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete
|
||||
|
||||
public IDeleteForeignKeyOnTableSyntax ForeignKey(string foreignKeyName)
|
||||
{
|
||||
var expression = _databaseProviders == null
|
||||
var expression = _databaseProviders == null
|
||||
? new DeleteForeignKeyExpression { ForeignKey = { Name = foreignKeyName } }
|
||||
: new DeleteForeignKeyExpression(_context.CurrentDatabaseProvider, _databaseProviders) { ForeignKey = { Name = foreignKeyName } };
|
||||
_context.Expressions.Add(expression);
|
||||
@@ -68,17 +68,17 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete
|
||||
|
||||
public IDeleteIndexForTableSyntax Index(string indexName)
|
||||
{
|
||||
var expression = new DeleteIndexExpression {Index = {Name = indexName}};
|
||||
var expression = new DeleteIndexExpression { Index = { Name = indexName } };
|
||||
_context.Expressions.Add(expression);
|
||||
return new DeleteIndexBuilder(expression);
|
||||
}
|
||||
|
||||
public IDeleteConstraintOnTableSyntax PrimaryKey(string primaryKeyName)
|
||||
{
|
||||
var expression = new DeleteConstraintExpression(ConstraintType.PrimaryKey)
|
||||
{
|
||||
Constraint = { ConstraintName = primaryKeyName }
|
||||
};
|
||||
var expression = new DeleteConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders, ConstraintType.PrimaryKey)
|
||||
{
|
||||
Constraint = { ConstraintName = primaryKeyName }
|
||||
};
|
||||
_context.Expressions.Add(expression);
|
||||
return new DeleteConstraintBuilder(expression);
|
||||
}
|
||||
@@ -86,16 +86,16 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete
|
||||
public IDeleteConstraintOnTableSyntax UniqueConstraint(string constraintName)
|
||||
{
|
||||
var expression = new DeleteConstraintExpression(ConstraintType.Unique)
|
||||
{
|
||||
Constraint = { ConstraintName = constraintName }
|
||||
};
|
||||
{
|
||||
Constraint = { ConstraintName = constraintName }
|
||||
};
|
||||
_context.Expressions.Add(expression);
|
||||
return new DeleteConstraintBuilder(expression);
|
||||
}
|
||||
|
||||
public IDeleteDefaultConstraintOnTableSyntax DefaultConstraint()
|
||||
{
|
||||
var expression = _databaseProviders == null
|
||||
var expression = _databaseProviders == null
|
||||
? new DeleteDefaultConstraintExpression()
|
||||
: new DeleteDefaultConstraintExpression(_context.CurrentDatabaseProvider, _databaseProviders);
|
||||
_context.Expressions.Add(expression);
|
||||
|
||||
+28
-1
@@ -10,13 +10,40 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
|
||||
Constraint = new ConstraintDefinition(type);
|
||||
}
|
||||
|
||||
public DeleteConstraintExpression(DatabaseProviders current, DatabaseProviders[] databaseProviders, ConstraintType type)
|
||||
: base(current, databaseProviders)
|
||||
{
|
||||
Constraint = new ConstraintDefinition(type);
|
||||
}
|
||||
|
||||
public ConstraintDefinition Constraint { get; private set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
|
||||
// Test for MySQL primary key situation.
|
||||
if (CurrentDatabaseProvider == DatabaseProviders.MySql)
|
||||
{
|
||||
if (Constraint.IsPrimaryKeyConstraint)
|
||||
{
|
||||
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Constraint.TableName),
|
||||
"PRIMARY KEY",
|
||||
"");
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Constraint.TableName),
|
||||
"FOREIGN KEY",
|
||||
"");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(Constraint.TableName),
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(Constraint.ConstraintName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -27,7 +27,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
|
||||
if (ForeignKey.ForeignTable == null)
|
||||
throw new ArgumentNullException("Table name not specified, ensure you have appended the OnTable extension. Format should be Delete.ForeignKey(KeyName).OnTable(TableName)");
|
||||
|
||||
if(CurrentDatabaseProvider == DatabaseProviders.MySql)
|
||||
if (CurrentDatabaseProvider == DatabaseProviders.MySql)
|
||||
{
|
||||
//MySql naming "convention" for foreignkeys, which aren't explicitly named
|
||||
if (string.IsNullOrEmpty(ForeignKey.Name))
|
||||
@@ -35,7 +35,7 @@ namespace Umbraco.Core.Persistence.Migrations.Syntax.Delete.Expressions
|
||||
|
||||
return string.Format(SqlSyntaxContext.SqlSyntaxProvider.DeleteConstraint,
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedTableName(ForeignKey.ForeignTable),
|
||||
"FOREIGN KEY ",
|
||||
"FOREIGN KEY",
|
||||
SqlSyntaxContext.SqlSyntaxProvider.GetQuotedName(ForeignKey.Name));
|
||||
}
|
||||
|
||||
|
||||
+7
-7
@@ -26,11 +26,11 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
|
||||
//create a new col which we will make a foreign key, but first needs to be populated with data.
|
||||
Alter.Table("cmsTagRelationship").AddColumn("propertyTypeId").AsInt32().Nullable();
|
||||
|
||||
//drop the foreign key on umbracoNode. Must drop foreign key first before primary key can be removed in MySql.
|
||||
Delete.ForeignKey("FK_cmsTagRelationship_umbracoNode_id").OnTable("cmsTagRelationship");
|
||||
|
||||
//we need to drop the primary key
|
||||
Delete.PrimaryKey("PK_cmsTagRelationship").FromTable("cmsTagRelationship");
|
||||
|
||||
//drop the foreign key on umbracoNode
|
||||
Delete.ForeignKey("FK_cmsTagRelationship_umbracoNode_id").OnTable("cmsTagRelationship");
|
||||
}
|
||||
|
||||
private void Upgrade()
|
||||
@@ -57,9 +57,9 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
|
||||
var propertyTypes = propertyTypeIdRef.Where(x => x.NodeId == tr.NodeId).ToArray();
|
||||
if (propertyTypes.Length == 0)
|
||||
{
|
||||
LogHelper.Warn<AlterTagRelationsTable>("There was no cmsContent reference for cmsTagRelationship for nodeId "
|
||||
LogHelper.Warn<AlterTagRelationsTable>("There was no cmsContent reference for cmsTagRelationship for nodeId "
|
||||
+ tr.NodeId +
|
||||
". The new tag system only supports tags with references to content in the cmsContent and cmsPropertyType tables. This row will be deleted: "
|
||||
". The new tag system only supports tags with references to content in the cmsContent and cmsPropertyType tables. This row will be deleted: "
|
||||
+ string.Format("nodeId: {0}, tagId: {1}", tr.NodeId, tr.TagId));
|
||||
Delete.FromTable("cmsTagRelationship").Row(new { nodeId = tr.NodeId, tagId = tr.TagId });
|
||||
}
|
||||
@@ -92,7 +92,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
|
||||
Alter.Table("cmsTagRelationship").AlterColumn("propertyTypeId").AsInt32().NotNullable();
|
||||
|
||||
//we need to re-add the new primary key on all 3 columns
|
||||
Create.PrimaryKey("PK_cmsTagRelationship").OnTable("cmsTagRelationship").Columns(new[] {"nodeId", "propertyTypeId", "tagId"});
|
||||
Create.PrimaryKey("PK_cmsTagRelationship").OnTable("cmsTagRelationship").Columns(new[] { "nodeId", "propertyTypeId", "tagId" });
|
||||
|
||||
//now we need to add a foreign key to the propertyTypeId column and change it's constraints
|
||||
Create.ForeignKey("FK_cmsTagRelationship_cmsPropertyType")
|
||||
@@ -102,7 +102,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSeven
|
||||
.PrimaryColumn("id")
|
||||
.OnDelete(Rule.None)
|
||||
.OnUpdate(Rule.None);
|
||||
|
||||
|
||||
//now we need to add a foreign key to the nodeId column to cmsContent (intead of the original umbracoNode)
|
||||
Create.ForeignKey("FK_cmsTagRelationship_cmsContent")
|
||||
.FromTable("cmsTagRelationship")
|
||||
|
||||
@@ -21,14 +21,18 @@ namespace Umbraco.Core.Persistence
|
||||
/// <summary>
|
||||
/// This will escape single @ symbols for peta poco values so it doesn't think it's a parameter
|
||||
/// </summary>
|
||||
/// <param name="db"></param>
|
||||
/// <param name="value"></param>
|
||||
/// <returns></returns>
|
||||
public static string EscapeAtSymbols(this Database db, string value)
|
||||
public static string EscapeAtSymbols(string value)
|
||||
{
|
||||
//this fancy regex will only match a single @ not a double, etc...
|
||||
var regex = new Regex("(?<!@)@(?!@)");
|
||||
return regex.Replace(value, "@@");
|
||||
if (value.Contains("@"))
|
||||
{
|
||||
//this fancy regex will only match a single @ not a double, etc...
|
||||
var regex = new Regex("(?<!@)@(?!@)");
|
||||
return regex.Replace(value, "@@");
|
||||
}
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
public static void CreateTable<T>(this Database db)
|
||||
@@ -336,6 +340,14 @@ namespace Umbraco.Core.Persistence
|
||||
creation.UninstallDatabaseSchema();
|
||||
}
|
||||
|
||||
internal static void CreateDatabaseSchemaDo(this Database db, bool guardConfiguration)
|
||||
{
|
||||
if (guardConfiguration && ApplicationContext.Current.IsConfigured)
|
||||
throw new Exception("Umbraco is already configured!");
|
||||
|
||||
CreateDatabaseSchemaDo(db);
|
||||
}
|
||||
|
||||
internal static void CreateDatabaseSchemaDo(this Database db)
|
||||
{
|
||||
NewTable += PetaPocoExtensions_NewTable;
|
||||
|
||||
@@ -64,13 +64,7 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
|
||||
public virtual string EscapeAtArgument(string exp)
|
||||
{
|
||||
/*if (exp.StartsWith("@"))
|
||||
return string.Concat("@", exp);*/
|
||||
|
||||
if (exp.Contains("@"))
|
||||
return exp.Replace("@", "@@");
|
||||
|
||||
return exp;
|
||||
return PetaPocoExtensions.EscapeAtSymbols(exp);
|
||||
}
|
||||
|
||||
public virtual bool ShouldQuoteValue(Type fieldType)
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
@@ -226,6 +228,41 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
|
||||
}
|
||||
|
||||
private string HandleStringComparison(string col, string val, string verb, TextColumnType columnType)
|
||||
{
|
||||
switch (verb)
|
||||
{
|
||||
case "SqlWildcard":
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnWildcardComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType);
|
||||
case "Equals":
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEqualComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType);
|
||||
case "StartsWith":
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnStartsWithComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType);
|
||||
case "EndsWith":
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnEndsWithComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType);
|
||||
case "Contains":
|
||||
return SqlSyntaxContext.SqlSyntaxProvider.GetStringColumnContainsComparison(col, EscapeAtArgument(RemoveQuote(val)), columnType);
|
||||
case "InvariantEquals":
|
||||
case "SqlEquals":
|
||||
//recurse
|
||||
return HandleStringComparison(col, val, "Equals", columnType);
|
||||
case "InvariantStartsWith":
|
||||
case "SqlStartsWith":
|
||||
//recurse
|
||||
return HandleStringComparison(col, val, "StartsWith", columnType);
|
||||
case "InvariantEndsWith":
|
||||
case "SqlEndsWith":
|
||||
//recurse
|
||||
return HandleStringComparison(col, val, "EndsWith", columnType);
|
||||
case "InvariantContains":
|
||||
case "SqlContains":
|
||||
//recurse
|
||||
return HandleStringComparison(col, val, "Contains", columnType);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("verb");
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual string VisitMethodCall(MethodCallExpression m)
|
||||
{
|
||||
List<Object> args = this.VisitExpressionList(m.Arguments);
|
||||
@@ -245,12 +282,31 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
return string.Format("upper({0})", r);
|
||||
case "ToLower":
|
||||
return string.Format("lower({0})", r);
|
||||
case "SqlWildcard":
|
||||
case "StartsWith":
|
||||
return string.Format("upper({0}) like '{1}%'", r, EscapeAtArgument(RemoveQuote(args[0].ToString().ToUpper())));
|
||||
case "EndsWith":
|
||||
return string.Format("upper({0}) like '%{1}'", r, EscapeAtArgument(RemoveQuote(args[0].ToString()).ToUpper()));
|
||||
case "Contains":
|
||||
return string.Format("{0} like '%{1}%'", r, EscapeAtArgument(RemoveQuote(args[0].ToString()).ToUpper()));
|
||||
case "Equals":
|
||||
case "SqlStartsWith":
|
||||
case "SqlEndsWith":
|
||||
case "SqlContains":
|
||||
case "SqlEquals":
|
||||
case "InvariantStartsWith":
|
||||
case "InvariantEndsWith":
|
||||
case "InvariantContains":
|
||||
case "InvariantEquals":
|
||||
//default
|
||||
var colType = TextColumnType.NVarchar;
|
||||
//then check if this arg has been passed in
|
||||
if (m.Arguments.Count > 1)
|
||||
{
|
||||
var colTypeArg = m.Arguments.FirstOrDefault(x => x is ConstantExpression && x.Type == typeof(TextColumnType));
|
||||
if (colTypeArg != null)
|
||||
{
|
||||
colType = (TextColumnType) ((ConstantExpression) colTypeArg).Value;
|
||||
}
|
||||
}
|
||||
return HandleStringComparison(r.ToString(), args[0].ToString(), m.Method.Name, colType);
|
||||
case "Substring":
|
||||
var startIndex = Int32.Parse(args[0].ToString()) + 1;
|
||||
if (args.Count == 2)
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
/// <summary>
|
||||
/// String extension methods used specifically to translate into SQL
|
||||
/// </summary>
|
||||
internal static class SqlStringExtensions
|
||||
{
|
||||
public static bool SqlWildcard(this string str, string txt, TextColumnType columnType)
|
||||
{
|
||||
var wildcardmatch = new Regex("^" + Regex.Escape(txt).
|
||||
//deal with any wildcard chars %
|
||||
Replace(@"\%", ".*") + "$");
|
||||
|
||||
return wildcardmatch.IsMatch(str);
|
||||
}
|
||||
|
||||
public static bool SqlContains(this string str, string txt, TextColumnType columnType)
|
||||
{
|
||||
return str.InvariantContains(txt);
|
||||
}
|
||||
|
||||
public static bool SqlEquals(this string str, string txt, TextColumnType columnType)
|
||||
{
|
||||
return str.InvariantEquals(txt);
|
||||
}
|
||||
|
||||
public static bool SqlStartsWith(this string str, string txt, TextColumnType columnType)
|
||||
{
|
||||
return str.InvariantStartsWith(txt);
|
||||
}
|
||||
|
||||
public static bool SqlEndsWith(this string str, string txt, TextColumnType columnType)
|
||||
{
|
||||
return str.InvariantEndsWith(txt);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines how to match a string property value
|
||||
/// </summary>
|
||||
public enum StringPropertyMatchType
|
||||
{
|
||||
Exact,
|
||||
Contains,
|
||||
StartsWith,
|
||||
EndsWith,
|
||||
//Deals with % as wildcard chars in a string
|
||||
Wildcard
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
public enum TextColumnType
|
||||
{
|
||||
NVarchar,
|
||||
NText
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
/// <summary>
|
||||
/// Determine how to match a number or data value
|
||||
/// </summary>
|
||||
public enum ValuePropertyMatchType
|
||||
{
|
||||
Exact,
|
||||
GreaterThan,
|
||||
LessThan,
|
||||
GreaterThanOrEqualTo,
|
||||
LessThanOrEqualTo
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Relators
|
||||
@@ -20,8 +21,12 @@ namespace Umbraco.Core.Persistence.Relators
|
||||
// Is this the same MemberReadOnlyDto as the current one we're processing
|
||||
if (Current != null && Current.UniqueId == a.UniqueId)
|
||||
{
|
||||
// Yes, just add this PropertyDataReadOnlyDto to the current MemberReadOnlyDto's collection
|
||||
Current.Properties.Add(p);
|
||||
//This property may already be added so we need to check for that
|
||||
if (Current.Properties.Any(x => x.Id == p.Id) == false)
|
||||
{
|
||||
// Yes, just add this PropertyDataReadOnlyDto to the current MemberReadOnlyDto's collection
|
||||
Current.Properties.Add(p);
|
||||
}
|
||||
|
||||
// Return null to indicate we're not done with this MemberReadOnlyDto yet
|
||||
return null;
|
||||
|
||||
@@ -273,7 +273,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
|
||||
//Assign the same permissions to it as the parent node
|
||||
// http://issues.umbraco.org/issue/U4-2161
|
||||
// http://issues.umbraco.org/issue/U4-2161
|
||||
var permissionsRepo = new PermissionRepository<IContent>(UnitOfWork);
|
||||
var parentPermissions = permissionsRepo.GetPermissionsForEntity(entity.ParentId).ToArray();
|
||||
//if there are parent permissions then assign them, otherwise leave null and permissions will become the
|
||||
@@ -284,7 +284,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
from perm in parentPermissions
|
||||
from p in perm.AssignedPermissions
|
||||
select new Tuple<object, string>(perm.UserId, p)).ToList();
|
||||
|
||||
|
||||
permissionsRepo.AssignEntityPermissions(entity, userPermissions);
|
||||
//flag the entity's permissions changed flag so we can track those changes.
|
||||
//Currently only used for the cache refreshers to detect if we should refresh all user permissions cache.
|
||||
|
||||
@@ -261,6 +261,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
foreach (var item in items)
|
||||
{
|
||||
//Before a PropertyType can be deleted, all Properties based on that PropertyType should be deleted.
|
||||
Database.Delete<TagRelationshipDto>("WHERE propertyTypeId = @Id", new { Id = item });
|
||||
Database.Delete<PropertyDataDto>("WHERE propertytypeid = @Id", new {Id = item});
|
||||
Database.Delete<PropertyTypeDto>("WHERE contentTypeId = @Id AND id = @PropertyTypeId",
|
||||
new {Id = entity.Id, PropertyTypeId = item});
|
||||
|
||||
@@ -180,7 +180,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
else
|
||||
{
|
||||
translation.Id = Convert.ToInt32(Database.Insert(dto));
|
||||
translation.Id = Convert.ToInt32(Database.Insert(textDto));
|
||||
translation.Key = entity.Key;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,16 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
get { return _fileSystem; }
|
||||
}
|
||||
|
||||
internal virtual void AddFolder(string folderPath)
|
||||
{
|
||||
_work.RegisterAdded(new Folder(folderPath), this);
|
||||
}
|
||||
|
||||
internal virtual void DeleteFolder(string folderPath)
|
||||
{
|
||||
_work.RegisterRemoved(new Folder(folderPath), this);
|
||||
}
|
||||
|
||||
#region Implementation of IRepository<TId,TEntity>
|
||||
|
||||
public virtual void AddOrUpdate(TEntity entity)
|
||||
@@ -68,7 +78,16 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public void PersistNewItem(IEntity entity)
|
||||
{
|
||||
PersistNewItem((TEntity)entity);
|
||||
//special case for folder
|
||||
var folder = entity as Folder;
|
||||
if (folder != null)
|
||||
{
|
||||
PersistNewFolder(folder);
|
||||
}
|
||||
else
|
||||
{
|
||||
PersistNewItem((TEntity)entity);
|
||||
}
|
||||
}
|
||||
|
||||
public void PersistUpdatedItem(IEntity entity)
|
||||
@@ -78,23 +97,46 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public void PersistDeletedItem(IEntity entity)
|
||||
{
|
||||
PersistDeletedItem((TEntity)entity);
|
||||
//special case for folder
|
||||
var folder = entity as Folder;
|
||||
if (folder != null)
|
||||
{
|
||||
PersistDeletedFolder(folder);
|
||||
}
|
||||
else
|
||||
{
|
||||
PersistDeletedItem((TEntity)entity);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Abstract IUnitOfWorkRepository Methods
|
||||
internal virtual void PersistNewFolder(Folder entity)
|
||||
{
|
||||
_fileSystem.CreateFolder(entity.Path);
|
||||
}
|
||||
|
||||
internal virtual void PersistDeletedFolder(Folder entity)
|
||||
{
|
||||
_fileSystem.DeleteDirectory(entity.Path);
|
||||
}
|
||||
|
||||
#region Abstract IUnitOfWorkRepository Methods
|
||||
|
||||
protected virtual void PersistNewItem(TEntity entity)
|
||||
{
|
||||
var stream = new MemoryStream(Encoding.UTF8.GetBytes(entity.Content));
|
||||
FileSystem.AddFile(entity.Name, stream, true);
|
||||
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(entity.Content)))
|
||||
{
|
||||
FileSystem.AddFile(entity.Path, stream, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void PersistUpdatedItem(TEntity entity)
|
||||
{
|
||||
var stream = new MemoryStream(Encoding.UTF8.GetBytes(entity.Content));
|
||||
FileSystem.AddFile(entity.Name, stream, true);
|
||||
using (var stream = new MemoryStream(Encoding.UTF8.GetBytes(entity.Content)))
|
||||
{
|
||||
FileSystem.AddFile(entity.Path, stream, true);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void PersistDeletedItem(TEntity entity)
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
@@ -12,5 +16,30 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <returns></returns>
|
||||
IEnumerable<IMember> GetByMemberGroup(string groupName);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a member with the username exists
|
||||
/// </summary>
|
||||
/// <param name="username"></param>
|
||||
/// <returns></returns>
|
||||
bool Exists(string username);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the count of items based on a complex query
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <returns></returns>
|
||||
int GetCountByQuery(IQuery<IMember> query);
|
||||
|
||||
/// <summary>
|
||||
/// Gets paged member results
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IMember> GetPagedResultsByQuery(IQuery<IMember> query, int pageIndex, int pageSize, out int totalRecords, Expression<Func<IMember, string>> orderBy);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IRelationRepository : IRepositoryQueryable<int, IRelation>
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IRelationTypeRepository : IRepositoryQueryable<int, IRelationType>
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
public interface IScriptRepository : IRepository<string, Script>
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -34,7 +34,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// Assigns the given tags to a content item's property
|
||||
/// </summary>
|
||||
/// <param name="contentId"></param>
|
||||
/// <param name="propertyTypeAlias"></param>
|
||||
/// <param name="propertyTypeId"></param>
|
||||
/// <param name="tags">The tags to assign</param>
|
||||
/// <param name="replaceTags">
|
||||
/// If set to true, this will replace all tags with the given tags,
|
||||
@@ -44,14 +44,14 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <remarks>
|
||||
/// This can also be used to remove all tags from a property by specifying replaceTags = true and an empty tag list.
|
||||
/// </remarks>
|
||||
void AssignTagsToProperty(int contentId, string propertyTypeAlias, IEnumerable<ITag> tags, bool replaceTags);
|
||||
void AssignTagsToProperty(int contentId, int propertyTypeId, IEnumerable<ITag> tags, bool replaceTags);
|
||||
|
||||
/// <summary>
|
||||
/// Removes any of the given tags from the property association
|
||||
/// </summary>
|
||||
/// <param name="contentId"></param>
|
||||
/// <param name="propertyTypeAlias"></param>
|
||||
/// <param name="propertyTypeId"></param>
|
||||
/// <param name="tags">The tags to remove from the property</param>
|
||||
void RemoveTagsFromProperty(int contentId, string propertyTypeAlias, IEnumerable<ITag> tags);
|
||||
void RemoveTagsFromProperty(int contentId, int propertyTypeId, IEnumerable<ITag> tags);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,45 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
internal interface IUserRepository : IRepositoryQueryable<int, IUser>
|
||||
{
|
||||
//IProfile GetProfileById(int id);
|
||||
IProfile GetProfileByUserName(string username);
|
||||
IUser GetUserByUserName(string username);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the count of items based on a complex query
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <returns></returns>
|
||||
int GetCountByQuery(IQuery<IUser> query);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if a user with the username exists
|
||||
/// </summary>
|
||||
/// <param name="username"></param>
|
||||
/// <returns></returns>
|
||||
bool Exists(string username);
|
||||
|
||||
/// <summary>
|
||||
/// This is useful when an entire section is removed from config
|
||||
/// </summary>
|
||||
/// <param name="sectionAlias"></param>
|
||||
IEnumerable<IUser> GetUsersAssignedToSection(string sectionAlias);
|
||||
|
||||
/// <summary>
|
||||
/// Gets paged member results
|
||||
/// </summary>
|
||||
/// <param name="query"></param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <returns></returns>
|
||||
IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, int pageIndex, int pageSize, out int totalRecords, Expression<Func<IUser, string>> orderBy);
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the user permissions for the specified entities
|
||||
/// </summary>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
@@ -9,6 +10,7 @@ using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.Relators;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
@@ -446,6 +448,89 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return BuildFromDtos(dtos);
|
||||
}
|
||||
|
||||
public bool Exists(string username)
|
||||
{
|
||||
var sql = new Sql();
|
||||
var escapedUserName = PetaPocoExtensions.EscapeAtSymbols(username);
|
||||
sql.Select("COUNT(*)")
|
||||
.From<MemberDto>()
|
||||
.Where<MemberDto>(x => x.LoginName == escapedUserName);
|
||||
|
||||
return Database.ExecuteScalar<int>(sql) > 0;
|
||||
}
|
||||
|
||||
public int GetCountByQuery(IQuery<IMember> query)
|
||||
{
|
||||
var sqlSubquery = GetSubquery();
|
||||
var translator = new SqlTranslator<IMember>(sqlSubquery, query);
|
||||
var subquery = translator.Translate();
|
||||
//get the COUNT base query
|
||||
var sql = GetBaseQuery(true)
|
||||
.Append(new Sql("WHERE umbracoNode.id IN (" + subquery.SQL + ")", subquery.Arguments));
|
||||
|
||||
return Database.ExecuteScalar<int>(sql);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets paged member results
|
||||
/// </summary>
|
||||
/// <param name="query">
|
||||
/// The where clause, if this is null all records are queried
|
||||
/// </param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// The query supplied will ONLY work with data specifically on the cmsMember table because we are using PetaPoco paging (SQL paging)
|
||||
/// </remarks>
|
||||
public IEnumerable<IMember> GetPagedResultsByQuery(IQuery<IMember> query, int pageIndex, int pageSize, out int totalRecords, Expression<Func<IMember, string>> orderBy)
|
||||
{
|
||||
if (orderBy == null) throw new ArgumentNullException("orderBy");
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*").From<MemberDto>();
|
||||
|
||||
Sql resultQuery;
|
||||
if (query != null)
|
||||
{
|
||||
var translator = new SqlTranslator<IMember>(sql, query);
|
||||
resultQuery = translator.Translate();
|
||||
}
|
||||
else
|
||||
{
|
||||
resultQuery = sql;
|
||||
}
|
||||
|
||||
|
||||
//get the referenced column name
|
||||
var expressionMember = ExpressionHelper.GetMemberInfo(orderBy);
|
||||
//now find the mapped column name
|
||||
var mapper = MappingResolver.Current.ResolveMapperByType(typeof(IMember));
|
||||
var mappedField = mapper.Map(expressionMember.Name);
|
||||
if (mappedField.IsNullOrWhiteSpace())
|
||||
{
|
||||
throw new ArgumentException("Could not find a mapping for the column specified in the orderBy clause");
|
||||
}
|
||||
//need to ensure the order by is in brackets, see: https://github.com/toptensoftware/PetaPoco/issues/177
|
||||
resultQuery.OrderBy(string.Format("({0})", mappedField));
|
||||
|
||||
var pagedResult = Database.Page<MemberDto>(pageIndex + 1, pageSize, resultQuery);
|
||||
|
||||
totalRecords = Convert.ToInt32(pagedResult.TotalItems);
|
||||
|
||||
//now that we have the member dto's we need to construct true members from the list.
|
||||
if (totalRecords == 0)
|
||||
{
|
||||
return Enumerable.Empty<IMember>();
|
||||
}
|
||||
var result = GetAll(pagedResult.Items.Select(x => x.NodeId).ToArray());
|
||||
|
||||
//now we need to ensure this result is also ordered by the same order by clause
|
||||
return result.OrderBy(orderBy.Compile());
|
||||
}
|
||||
|
||||
private IMember BuildFromDto(List<MemberReadOnlyDto> dtos)
|
||||
{
|
||||
if (dtos == null || dtos.Any() == false)
|
||||
|
||||
@@ -168,7 +168,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
((MemberType)entity).AddingEntity();
|
||||
|
||||
//By Convention we add 9 stnd PropertyTypes to an Umbraco MemberType
|
||||
var standardPropertyTypes = Constants.Conventions.Member.StandardPropertyTypeStubs;
|
||||
var standardPropertyTypes = Constants.Conventions.Member.GetStandardPropertyTypeStubs();
|
||||
foreach (var standardPropertyType in standardPropertyTypes)
|
||||
{
|
||||
entity.AddPropertyType(standardPropertyType.Value);
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.UnitOfWork;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
internal class NotificationsRepository
|
||||
{
|
||||
private readonly IDatabaseUnitOfWork _unitOfWork;
|
||||
|
||||
public NotificationsRepository(IDatabaseUnitOfWork unitOfWork)
|
||||
{
|
||||
_unitOfWork = unitOfWork;
|
||||
}
|
||||
|
||||
public IEnumerable<Notification> GetUserNotifications(IUser user)
|
||||
{
|
||||
var sql = new Sql()
|
||||
.Select("DISTINCT umbracoNode.id, umbracoUser2NodeNotify.userId, umbracoNode.nodeObjectType, umbracoUser2NodeNotify.action")
|
||||
.From<User2NodeNotifyDto>()
|
||||
.InnerJoin<NodeDto>()
|
||||
.On<User2NodeNotifyDto, NodeDto>(dto => dto.NodeId, dto => dto.NodeId)
|
||||
.Where<User2NodeNotifyDto>(dto => dto.UserId == (int)user.Id)
|
||||
.OrderBy<NodeDto>(dto => dto.NodeId);
|
||||
|
||||
var dtos = _unitOfWork.Database.Fetch<dynamic>(sql);
|
||||
//need to map the results
|
||||
return dtos.Select(d => new Notification(d.id, d.userId, d.action, d.nodeObjectType)).ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<Notification> GetEntityNotifications(IEntity entity)
|
||||
{
|
||||
var sql = new Sql()
|
||||
.Select("DISTINCT umbracoNode.id, umbracoUser2NodeNotify.userId, umbracoNode.nodeObjectType, umbracoUser2NodeNotify.action")
|
||||
.From<User2NodeNotifyDto>()
|
||||
.InnerJoin<NodeDto>()
|
||||
.On<User2NodeNotifyDto, NodeDto>(dto => dto.NodeId, dto => dto.NodeId)
|
||||
.Where<User2NodeNotifyDto>(dto => dto.NodeId == entity.Id)
|
||||
.OrderBy<NodeDto>(dto => dto.NodeId);
|
||||
|
||||
var dtos = _unitOfWork.Database.Fetch<dynamic>(sql);
|
||||
//need to map the results
|
||||
return dtos.Select(d => new Notification(d.id, d.userId, d.action, d.nodeObjectType)).ToList();
|
||||
}
|
||||
|
||||
public int DeleteNotifications(IEntity entity)
|
||||
{
|
||||
return _unitOfWork.Database.Delete<User2NodeNotifyDto>("WHERE nodeId = @nodeId", new { nodeId = entity.Id });
|
||||
}
|
||||
|
||||
public int DeleteNotifications(IUser user)
|
||||
{
|
||||
return _unitOfWork.Database.Delete<User2NodeNotifyDto>("WHERE userId = @userId", new { userId = user.Id });
|
||||
}
|
||||
|
||||
public int DeleteNotifications(IUser user, IEntity entity)
|
||||
{
|
||||
// delete all settings on the node for this user
|
||||
return _unitOfWork.Database.Delete<User2NodeNotifyDto>("WHERE userId = @userId AND nodeId = @nodeId", new { userId = user.Id, nodeId = entity.Id });
|
||||
}
|
||||
|
||||
public Notification CreateNotification(IUser user, IEntity entity, string action)
|
||||
{
|
||||
var sql = new Sql()
|
||||
.Select("DISTINCT nodeObjectType")
|
||||
.From<NodeDto>()
|
||||
.Where<NodeDto>(nodeDto => nodeDto.NodeId == entity.Id);
|
||||
var nodeType = _unitOfWork.Database.ExecuteScalar<Guid>(sql);
|
||||
|
||||
var dto = new User2NodeNotifyDto()
|
||||
{
|
||||
Action = action,
|
||||
NodeId = entity.Id,
|
||||
UserId = (int)user.Id
|
||||
};
|
||||
_unitOfWork.Database.Insert(dto);
|
||||
return new Notification(dto.NodeId, dto.UserId, dto.Action, nodeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,11 +110,11 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
internal void AssignEntityPermissions(TEntity entity, char permission, IEnumerable<object> userIds)
|
||||
{
|
||||
var actions = userIds.Select(id => new User2NodePermissionDto
|
||||
{
|
||||
NodeId = entity.Id,
|
||||
Permission = permission.ToString(CultureInfo.InvariantCulture),
|
||||
UserId = (int)id
|
||||
});
|
||||
{
|
||||
NodeId = entity.Id,
|
||||
Permission = permission.ToString(CultureInfo.InvariantCulture),
|
||||
UserId = (int)id
|
||||
});
|
||||
|
||||
_unitOfWork.Database.BulkInsertRecords(actions);
|
||||
}
|
||||
@@ -163,14 +163,14 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
_unitOfWork.Database.Update<User2NodePermissionDto>(
|
||||
GenerateReplaceEntityPermissionsSql(
|
||||
new[] {entity.Id}.Concat(getDescendantIds(entity)).ToArray(),
|
||||
permissions,
|
||||
new[] { entity.Id }.Concat(getDescendantIds(entity)).ToArray(),
|
||||
permissions,
|
||||
userIds.ToArray()));
|
||||
}
|
||||
|
||||
internal static string GenerateReplaceEntityPermissionsSql(int entityId, string permissions, object[] userIds)
|
||||
{
|
||||
return GenerateReplaceEntityPermissionsSql(new[] {entityId}, permissions, userIds);
|
||||
return GenerateReplaceEntityPermissionsSql(new[] { entityId }, permissions, userIds);
|
||||
}
|
||||
|
||||
internal static string GenerateReplaceEntityPermissionsSql(int[] entityIds, string permissions, object[] userIds)
|
||||
@@ -182,7 +182,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
//build the nodeIds part of the where clause
|
||||
var sqlNodeWhere = BuildOrClause(entityIds, "nodeId");
|
||||
|
||||
|
||||
//build up the userIds part of the where clause
|
||||
var userWhereBuilder = BuildOrClause(userIds, "userId");
|
||||
|
||||
@@ -211,5 +211,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
userWhereBuilder.Append(")");
|
||||
return userWhereBuilder.ToString();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -18,13 +18,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
{
|
||||
private readonly IRelationTypeRepository _relationTypeRepository;
|
||||
|
||||
public RelationRepository(IDatabaseUnitOfWork work, IRelationTypeRepository relationTypeRepository)
|
||||
: base(work)
|
||||
public RelationRepository(IDatabaseUnitOfWork work, IRelationTypeRepository relationTypeRepository)
|
||||
: base(work)
|
||||
{
|
||||
_relationTypeRepository = relationTypeRepository;
|
||||
}
|
||||
|
||||
public RelationRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IRelationTypeRepository relationTypeRepository)
|
||||
public RelationRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache, IRelationTypeRepository relationTypeRepository)
|
||||
: base(work, cache)
|
||||
{
|
||||
_relationTypeRepository = relationTypeRepository;
|
||||
@@ -42,7 +42,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return null;
|
||||
|
||||
var relationType = _relationTypeRepository.Get(dto.RelationType);
|
||||
if(relationType == null)
|
||||
if (relationType == null)
|
||||
throw new Exception(string.Format("RelationType with Id: {0} doesn't exist", dto.RelationType));
|
||||
|
||||
var factory = new RelationFactory(relationType);
|
||||
|
||||
@@ -16,12 +16,12 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// </summary>
|
||||
internal class RelationTypeRepository : PetaPocoRepositoryBase<int, IRelationType>, IRelationTypeRepository
|
||||
{
|
||||
public RelationTypeRepository(IDatabaseUnitOfWork work)
|
||||
: base(work)
|
||||
public RelationTypeRepository(IDatabaseUnitOfWork work)
|
||||
: base(work)
|
||||
{
|
||||
}
|
||||
|
||||
public RelationTypeRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache)
|
||||
public RelationTypeRepository(IDatabaseUnitOfWork work, IRepositoryCacheProvider cache)
|
||||
: base(work, cache)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -28,9 +28,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
|
||||
public override Script Get(string id)
|
||||
{
|
||||
if(!FileSystem.FileExists(id))
|
||||
if(FileSystem.FileExists(id) == false)
|
||||
{
|
||||
throw new Exception(string.Format("The file {0} was not found", id));
|
||||
return null;
|
||||
//throw new Exception(string.Format("The file {0} was not found", id));
|
||||
}
|
||||
|
||||
string content = string.Empty;
|
||||
|
||||
@@ -230,7 +230,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// Assigns the given tags to a content item's property
|
||||
/// </summary>
|
||||
/// <param name="contentId"></param>
|
||||
/// <param name="propertyTypeAlias"></param>
|
||||
/// <param name="propertyTypeId"></param>
|
||||
/// <param name="tags">The tags to assign</param>
|
||||
/// <param name="replaceTags">
|
||||
/// If set to true, this will replace all tags with the given tags,
|
||||
@@ -240,7 +240,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <remarks>
|
||||
/// This can also be used to remove all tags from a property by specifying replaceTags = true and an empty tag list.
|
||||
/// </remarks>
|
||||
public void AssignTagsToProperty(int contentId, string propertyTypeAlias, IEnumerable<ITag> tags, bool replaceTags)
|
||||
//public void AssignTagsToProperty(int contentId, string propertyTypeAlias, IEnumerable<ITag> tags, bool replaceTags)
|
||||
public void AssignTagsToProperty(int contentId, int propertyTypeId, IEnumerable<ITag> tags, bool replaceTags)
|
||||
{
|
||||
//First we need to ensure there are no duplicates
|
||||
var asArray = tags.Distinct(new TagComparer()).ToArray();
|
||||
@@ -251,8 +252,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return;
|
||||
}
|
||||
|
||||
var propertyTypeId = EnsureContentProperty(contentId, propertyTypeAlias);
|
||||
|
||||
//next check if we're removing all of the tags
|
||||
if (asArray.Length == 0 && replaceTags)
|
||||
{
|
||||
@@ -310,7 +309,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
"left outer join cmsTagRelationship ",
|
||||
"on (cmsTagRelationship.TagId = NewTagsSet.Id and cmsTagRelationship.nodeId = ",
|
||||
contentId,
|
||||
"and cmsTagRelationship.propertyTypeId = ",
|
||||
" and cmsTagRelationship.propertyTypeId = ",
|
||||
propertyTypeId,
|
||||
") ",
|
||||
"where cmsTagRelationship.tagId is null ");
|
||||
@@ -327,12 +326,10 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// Removes any of the given tags from the property association
|
||||
/// </summary>
|
||||
/// <param name="contentId"></param>
|
||||
/// <param name="propertyTypeAlias"></param>
|
||||
/// <param name="propertyTypeId"></param>
|
||||
/// <param name="tags">The tags to remove from the property</param>
|
||||
public void RemoveTagsFromProperty(int contentId, string propertyTypeAlias, IEnumerable<ITag> tags)
|
||||
public void RemoveTagsFromProperty(int contentId, int propertyTypeId, IEnumerable<ITag> tags)
|
||||
{
|
||||
var propertyTypeId = EnsureContentProperty(contentId, propertyTypeAlias);
|
||||
|
||||
var tagSetSql = GetTagSet(tags);
|
||||
|
||||
var deleteSql = string.Concat("DELETE FROM cmsTagRelationship WHERE nodeId = ",
|
||||
@@ -376,7 +373,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
/// <returns></returns>
|
||||
private static string GetTagSet(IEnumerable<ITag> tagsToInsert)
|
||||
{
|
||||
var array = tagsToInsert.Select(tag => string.Format("select '{0}' as Tag, '{1}' as [Group]", tag.Text, tag.Group)).ToArray();
|
||||
var array = tagsToInsert.Select(tag => string.Format("select '{0}' as Tag, '{1}' as [Group]", tag.Text.Replace("'", "''"), tag.Group)).ToArray();
|
||||
return "(" + string.Join(" union ", array).Replace(" ", " ") + ") as TagSet";
|
||||
}
|
||||
|
||||
@@ -396,36 +393,5 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Ensures the content and property alias exist, then returns the property type id for the alias
|
||||
/// </summary>
|
||||
/// <param name="contentId"></param>
|
||||
/// <param name="propertyAlias"></param>
|
||||
/// <returns></returns>
|
||||
private int EnsureContentProperty(int contentId, string propertyAlias)
|
||||
{
|
||||
//ensure that there's content and a property to assign - NOTE: we cannot use the content repository here
|
||||
// because the content repository requires one of us TagsRepository instance, then we'll have circular dependencies
|
||||
// instead we'll just look it up ourselves.
|
||||
|
||||
var sql = new Sql()
|
||||
.Select("cmsPropertyType.id")
|
||||
.From<ContentDto>()
|
||||
.InnerJoin<ContentTypeDto>()
|
||||
.On<ContentTypeDto, ContentDto>(left => left.NodeId, right => right.ContentTypeId)
|
||||
.InnerJoin<PropertyTypeDto>()
|
||||
.On<PropertyTypeDto, ContentTypeDto>(left => left.ContentTypeId, right => right.NodeId)
|
||||
.Where<ContentDto>(dto => dto.NodeId == contentId)
|
||||
.Where<PropertyTypeDto>(dto => dto.Alias == propertyAlias);
|
||||
|
||||
var result = Database.Fetch<int>(sql).ToArray();
|
||||
|
||||
if (result.Length == 0)
|
||||
{
|
||||
throw new InvalidOperationException("Cannot modify tags for content id " + contentId + " and property " + propertyAlias + " because the content item does not exist with this property");
|
||||
}
|
||||
|
||||
return result.First();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.Caching;
|
||||
using Umbraco.Core.Persistence.Factories;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Persistence.Querying;
|
||||
using Umbraco.Core.Persistence.Relators;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
@@ -200,7 +202,30 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
#endregion
|
||||
|
||||
#region Implementation of IUserRepository
|
||||
|
||||
|
||||
public int GetCountByQuery(IQuery<IUser> query)
|
||||
{
|
||||
var sqlClause = GetBaseQuery("umbracoUser.id");
|
||||
var translator = new SqlTranslator<IUser>(sqlClause, query);
|
||||
var subquery = translator.Translate();
|
||||
//get the COUNT base query
|
||||
var sql = GetBaseQuery(true)
|
||||
.Append(new Sql("WHERE umbracoUser.id IN (" + subquery.SQL + ")", subquery.Arguments));
|
||||
|
||||
return Database.ExecuteScalar<int>(sql);
|
||||
}
|
||||
|
||||
public bool Exists(string username)
|
||||
{
|
||||
var sql = new Sql();
|
||||
var escapedUserName = PetaPocoExtensions.EscapeAtSymbols(username);
|
||||
sql.Select("COUNT(*)")
|
||||
.From<UserDto>()
|
||||
.Where<UserDto>(x => x.UserName == escapedUserName);
|
||||
|
||||
return Database.ExecuteScalar<int>(sql) > 0;
|
||||
}
|
||||
|
||||
public IEnumerable<IUser> GetUsersAssignedToSection(string sectionAlias)
|
||||
{
|
||||
//Here we're building up a query that looks like this, a sub query is required because the resulting structure
|
||||
@@ -224,6 +249,66 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return ConvertFromDtos(Database.Fetch<UserDto, User2AppDto, UserDto>(new UserSectionRelator().Map, sql));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets paged user results
|
||||
/// </summary>
|
||||
/// <param name="query">
|
||||
/// The where clause, if this is null all records are queried
|
||||
/// </param>
|
||||
/// <param name="pageIndex"></param>
|
||||
/// <param name="pageSize"></param>
|
||||
/// <param name="totalRecords"></param>
|
||||
/// <param name="orderBy"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// The query supplied will ONLY work with data specifically on the umbracoUser table because we are using PetaPoco paging (SQL paging)
|
||||
/// </remarks>
|
||||
public IEnumerable<IUser> GetPagedResultsByQuery(IQuery<IUser> query, int pageIndex, int pageSize, out int totalRecords, Expression<Func<IUser, string>> orderBy)
|
||||
{
|
||||
if (orderBy == null) throw new ArgumentNullException("orderBy");
|
||||
|
||||
var sql = new Sql();
|
||||
sql.Select("*").From<UserDto>();
|
||||
|
||||
Sql resultQuery;
|
||||
if (query != null)
|
||||
{
|
||||
var translator = new SqlTranslator<IUser>(sql, query);
|
||||
resultQuery = translator.Translate();
|
||||
}
|
||||
else
|
||||
{
|
||||
resultQuery = sql;
|
||||
}
|
||||
|
||||
//get the referenced column name
|
||||
var expressionMember = ExpressionHelper.GetMemberInfo(orderBy);
|
||||
//now find the mapped column name
|
||||
var mapper = MappingResolver.Current.ResolveMapperByType(typeof(IUser));
|
||||
var mappedField = mapper.Map(expressionMember.Name);
|
||||
if (mappedField.IsNullOrWhiteSpace())
|
||||
{
|
||||
throw new ArgumentException("Could not find a mapping for the column specified in the orderBy clause");
|
||||
}
|
||||
//need to ensure the order by is in brackets, see: https://github.com/toptensoftware/PetaPoco/issues/177
|
||||
resultQuery.OrderBy(string.Format("({0})", mappedField));
|
||||
|
||||
var pagedResult = Database.Page<UserDto>(pageIndex + 1, pageSize, resultQuery);
|
||||
|
||||
totalRecords = Convert.ToInt32(pagedResult.TotalItems);
|
||||
|
||||
//now that we have the user dto's we need to construct true members from the list.
|
||||
if (totalRecords == 0)
|
||||
{
|
||||
return Enumerable.Empty<IUser>();
|
||||
}
|
||||
|
||||
var result = GetAll(pagedResult.Items.Select(x => x.Id).ToArray());
|
||||
|
||||
//now we need to ensure this result is also ordered by the same order by clause
|
||||
return result.OrderBy(orderBy.Compile());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns permissions for a given user for any number of nodes
|
||||
/// </summary>
|
||||
@@ -236,63 +321,6 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
return repo.GetUserPermissionsForEntities(userId, entityIds);
|
||||
}
|
||||
|
||||
public IProfile GetProfileByUserName(string username)
|
||||
{
|
||||
var sql = GetBaseQuery(false);
|
||||
sql.Where("umbracoUser.userLogin = @Username", new { Username = username });
|
||||
|
||||
var dto = Database.FirstOrDefault<UserDto>(sql);
|
||||
|
||||
if (dto == null)
|
||||
return null;
|
||||
|
||||
return new Profile(dto.Id, dto.UserName);
|
||||
}
|
||||
|
||||
public IUser GetUserByUserName(string username)
|
||||
{
|
||||
var sql = GetBaseQuery(false);
|
||||
sql.Where("umbracoUser.userLogin = @Username", new { Username = username });
|
||||
|
||||
var dto = Database.FirstOrDefault<UserDto>(sql);
|
||||
|
||||
if (dto == null)
|
||||
return null;
|
||||
|
||||
return new User(_userTypeRepository.Get(dto.Type))
|
||||
{
|
||||
Id = dto.Id,
|
||||
Email = dto.Email,
|
||||
Language = dto.UserLanguage,
|
||||
Name = dto.UserName,
|
||||
NoConsole = dto.NoConsole,
|
||||
IsLockedOut = dto.Disabled
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
public IUser GetUserById(int id)
|
||||
{
|
||||
var sql = GetBaseQuery(false);
|
||||
sql.Where(GetBaseWhereClause(), new { Id = id });
|
||||
|
||||
var dto = Database.FirstOrDefault<UserDto>(sql);
|
||||
|
||||
if (dto == null)
|
||||
return null;
|
||||
|
||||
return new User(_userTypeRepository.Get(dto.Type))
|
||||
{
|
||||
Id = dto.Id,
|
||||
Email = dto.Email,
|
||||
Language = dto.UserLanguage,
|
||||
Name = dto.UserName,
|
||||
NoConsole = dto.NoConsole,
|
||||
IsLockedOut = dto.Disabled
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private IEnumerable<IUser> ConvertFromDtos(IEnumerable<UserDto> dtos)
|
||||
|
||||
@@ -106,7 +106,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
//remove the specific tags
|
||||
tagRepo.RemoveTagsFromProperty(
|
||||
entity.Id,
|
||||
tagProp.Alias,
|
||||
tagProp.PropertyTypeId,
|
||||
tagProp.TagSupport.Tags.Select(x => new Tag { Text = x.Item1, Group = x.Item2 }));
|
||||
}
|
||||
else
|
||||
@@ -114,7 +114,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
//assign the tags
|
||||
tagRepo.AssignTagsToProperty(
|
||||
entity.Id,
|
||||
tagProp.Alias,
|
||||
tagProp.PropertyTypeId,
|
||||
tagProp.TagSupport.Tags.Select(x => new Tag { Text = x.Item1, Group = x.Item2 }),
|
||||
tagProp.TagSupport.Behavior == PropertyTagBehavior.Replace);
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user