Compare commits
718 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| b0a739b4ac | |||
| 728dee070f | |||
| 4a735770e2 | |||
| d54b3a0cc3 | |||
| f962a3db20 | |||
| 39851d2475 | |||
| 28adbc17ef | |||
| 4b9a13078e | |||
| 17cce9a666 | |||
| 39da34e1c7 | |||
| 55dc927c8b | |||
| 6e3ff59dfb | |||
| 08eab00627 | |||
| c4fae9b272 | |||
| 51186bea24 | |||
| 5c5bacaab4 | |||
| 5a4e6df99c | |||
| 22f8a4c5dd | |||
| aaf7ae0331 | |||
| 8459a058c6 | |||
| dc5089a9d6 | |||
| 45a246d8b6 | |||
| 65bcd78872 | |||
| a0fd7001e9 | |||
| 09ceb15d08 | |||
| 25335446d0 | |||
| 63d8ef7560 | |||
| 27428bf545 | |||
| b9c418e458 | |||
| c843e634ba | |||
| 8eb0d254da | |||
| 70921e88f6 | |||
| d9b71995e1 | |||
| f517e750b9 | |||
| 07d91ce9ac | |||
| ac8ee92bb8 | |||
| aee06c4574 | |||
| d0f69907db | |||
| 71db33f4cd | |||
| cec6322a84 | |||
| eb85e8cd78 | |||
| cf7c0dffb0 | |||
| 78d91a353a | |||
| 22d778ed28 | |||
| a3a2b6499e | |||
| 65ed69cf06 | |||
| c09cd95eb6 | |||
| 1d3490eb82 | |||
| b78c334589 | |||
| b41de9b623 | |||
| c51d29da52 | |||
| 54967e0150 | |||
| 73e47402cb | |||
| 79844154fb | |||
| 067a1ba8e6 | |||
| 120cb964a5 | |||
| 147a1daf6d | |||
| 9badb35c05 | |||
| 765decf3b1 | |||
| eb35791003 | |||
| 69775c369a | |||
| 3f25d3637a | |||
| 02136d3060 | |||
| 99d4b13bb0 | |||
| e7b007386a | |||
| 5dc3e0a3fc | |||
| d146df43e6 | |||
| 451826a329 | |||
| 080150baa3 | |||
| c6bc5ae6aa | |||
| f84d3b435b | |||
| 99855bce11 | |||
| d0b2f10a8c | |||
| 70507501bd | |||
| bbfd570b8a | |||
| 4a593a0814 | |||
| 3cc0df0273 | |||
| 712cd29fea | |||
| 3d21448f89 | |||
| 7b4912b1e7 | |||
| 8c6362d947 | |||
| 01dd28fc61 | |||
| 67e2c911f7 | |||
| 36e60c774f | |||
| 745252341f | |||
| a2df4c5232 | |||
| d012d8e8b6 | |||
| 9318da2883 | |||
| a08849f60a | |||
| 9792d8df25 | |||
| 635cfe6b20 | |||
| 9ccf7bdbab | |||
| 0c520f2b43 | |||
| 85d10014c2 | |||
| 3c4b3f44c7 | |||
| c6956b5e98 | |||
| fcf5ecc166 | |||
| c5c87ff50d | |||
| eb949e2cbc | |||
| 8a096cd826 | |||
| 3b236ba724 | |||
| e7eaf6959f | |||
| 3e294e290b | |||
| 751dc8df23 | |||
| 91047182fa | |||
| 1030fd5294 | |||
| be2eb3f555 | |||
| 0eafa14246 | |||
| b807b84466 | |||
| ab551b2c96 | |||
| 1520fa77d5 | |||
| c1853e8c51 | |||
| 31c965ae42 | |||
| d91fc6ce60 | |||
| d5124e9739 | |||
| d9b507c947 | |||
| d3fcdfb176 | |||
| 2479c5a272 | |||
| fee071db22 | |||
| 004e00599d | |||
| 2e2e8b43b0 | |||
| e77c5f8667 | |||
| 3509a2c40f | |||
| 378d0f7939 | |||
| d64fa7f92d | |||
| ea14170272 | |||
| 73209d7e2c | |||
| cf8ead62ac | |||
| 8461aea7d8 | |||
| 034de1651b | |||
| dcb8aa7e56 | |||
| e8a52a95da | |||
| 42c99e0f07 | |||
| a31b368b60 | |||
| 77f6d28a74 | |||
| 0b8d3ef214 | |||
| a4f83f9c00 | |||
| 85467976ad | |||
| d7e93fe466 | |||
| 660f048b4f | |||
| 9fa76a0133 | |||
| 444c444f0e | |||
| 383bbbe7e0 | |||
| 72eddca3c6 | |||
| 7c2ddde311 | |||
| c6229e4fcb | |||
| fbac0aba8b | |||
| f01511c592 | |||
| 187354f0bd | |||
| 2f540b1bfa | |||
| b1f104d1de | |||
| ba5fcad09a | |||
| d553eb2978 | |||
| d1e6c0e835 | |||
| 244977dc95 | |||
| 3242b31a8a | |||
| efc3261163 | |||
| 8c6aa9875d | |||
| f89ce1ff26 | |||
| 1274fbaefd | |||
| 8140dfdc04 | |||
| a69eba61c8 | |||
| 46078a841c | |||
| 0eb5e5f6e4 | |||
| ec9020f63e | |||
| 0b61685fc8 | |||
| 3779b3c782 | |||
| 5b0e824301 | |||
| d24b0aa9eb | |||
| 9cd7e09986 | |||
| 9f505a7976 | |||
| f737004544 | |||
| 850e354b11 | |||
| 1b27114014 | |||
| d8b235ad62 | |||
| 56581478c8 | |||
| 2be330d237 | |||
| 4381a700ba | |||
| 99821954f1 | |||
| 10a15be8ad | |||
| 0a2830aece | |||
| d1094eea7a | |||
| c629a50f39 | |||
| 430f906ae6 | |||
| 736798c769 | |||
| e913034d93 | |||
| bed5f8a03b | |||
| 0291ab615d | |||
| ceeea7827e | |||
| 756b4d24c0 | |||
| ffe3fc9257 | |||
| 26bd3c7c0b | |||
| 944b3dcaac | |||
| ba489afe9a | |||
| 968d52e490 | |||
| ebbe9f6ed0 | |||
| ba32636fe7 | |||
| a6f9d14a1b | |||
| 7cd385dd6b | |||
| 5d4a97591a | |||
| bfb81f6362 | |||
| 23816665f3 | |||
| ca3dc030bc | |||
| 4775aff749 | |||
| 9d20ee293b | |||
| a9b820de31 | |||
| 3813653852 | |||
| a4720a2221 | |||
| 81354cea3c | |||
| 728b71c4bd | |||
| 9d7975d970 | |||
| 7505401511 | |||
| 7ee0a278f7 | |||
| 1adbe9ddcb | |||
| 67e3ec2ae0 | |||
| d6272b0cdb | |||
| ce7dd19a8f | |||
| d295174e53 | |||
| 55022e2aaf | |||
| 4ffca2e4bf | |||
| 4a38b8acd1 | |||
| d93b8b869e | |||
| bec4e442fb | |||
| b88e714050 | |||
| da8c46e426 | |||
| 72cc5ce88b | |||
| 63763d025e | |||
| f76fa6bde6 | |||
| c34a1060f7 | |||
| a231cedd8e | |||
| 20526b40bf | |||
| 5008a2be7f | |||
| 03a395d1f9 | |||
| 734df8685d | |||
| 92dad1af1c | |||
| d897e78b27 | |||
| d79115fcdf | |||
| 992073ab4e | |||
| 3c9b144927 | |||
| b7e4f58503 | |||
| 5880df3859 | |||
| c11dce7b6e | |||
| 004a3e2808 | |||
| d05bfc8983 | |||
| 5bb7223a79 | |||
| c9a816f25e | |||
| 13cfb42287 | |||
| 334fcf38ec | |||
| 8873d0f79d | |||
| b499b45a5c | |||
| d5a71ec1da | |||
| 1402494e47 | |||
| 7c491c1fc1 | |||
| 460dd69884 | |||
| beda99963e | |||
| b06f16f5f7 | |||
| f9d79871b4 | |||
| 777b02b84c | |||
| e322ab6f75 | |||
| d19bebc404 | |||
| 46dd86c745 | |||
| 62af834176 | |||
| 2dac1b3cf5 | |||
| 68fb951283 | |||
| 1ca825de62 | |||
| 13ccd86192 | |||
| 336266c0eb | |||
| 54b57f7d51 | |||
| 2f6e161120 | |||
| 379bbe5bc4 | |||
| 5c558b0eeb | |||
| 298e56ad05 | |||
| d74d2cd945 | |||
| e2dc4f36ad | |||
| 9620c902cc | |||
| abda579da6 | |||
| 2e43e97ae2 | |||
| c7ac3e7691 | |||
| a209a2067c | |||
| 58f9ff4b79 | |||
| b1c6276a67 | |||
| 3950b35539 | |||
| 2f63364925 | |||
| 376c78381d | |||
| 0a09810f0f | |||
| 43018e2793 | |||
| ba559f6836 | |||
| a320b63fd6 | |||
| 200497b865 | |||
| 8bd38b3cdd | |||
| f2c7c1e2c6 | |||
| 9f2c428a7c | |||
| a958f946ef | |||
| ac642619e7 | |||
| 688652fb91 | |||
| 4ef1eeb8bc | |||
| 0d7661a779 | |||
| 17f36c62cb | |||
| 5a98150f15 | |||
| d6bc0934ff | |||
| 29caacf3c3 | |||
| f091219f48 | |||
| 372a2f5df4 | |||
| 1397bc6dbf | |||
| 7c5a4d9d67 | |||
| 183103dc16 | |||
| 4b2a5f8768 | |||
| 2c3693ac68 | |||
| 7d90296e15 | |||
| d4c831864d | |||
| 1a56bb9948 | |||
| 4e84260619 | |||
| 62ddce60a5 | |||
| bc8829ce14 | |||
| d582d5c827 | |||
| 604bddabdf | |||
| e5af5bcc22 | |||
| 9f7f920229 | |||
| d1d98372cd | |||
| 9feee42430 | |||
| 876cb374ad | |||
| 16582c8207 | |||
| 2ee1df3dec | |||
| fc862f8434 | |||
| 8d7891d203 | |||
| 5af773d1b0 | |||
| 847ef34281 | |||
| a728f475aa | |||
| 60f91d95e9 | |||
| 821532cbd4 | |||
| e3a639b424 | |||
| 5c49aa9b43 | |||
| f040754547 | |||
| 0da8604639 | |||
| dd09ba3e12 | |||
| 896ea389a3 | |||
| 759c6dfef2 | |||
| 809a3f952e | |||
| dce9dea8f3 | |||
| b2a497ddba | |||
| ea030d990f | |||
| de9739118e | |||
| 31767a4152 | |||
| d79134c710 | |||
| 2ed4948619 | |||
| ce08749d85 | |||
| 0e67c787a8 | |||
| 1eea1f5f8f | |||
| ebfb2b536f | |||
| 81010444f3 | |||
| bbbc1949bc | |||
| 7b34e59222 | |||
| 3706405bff | |||
| 8a0efd7790 | |||
| bd2ac3d128 | |||
| c25b710b80 | |||
| 09e060ff92 | |||
| 2248a85876 | |||
| a3f4b2db5d | |||
| 5947f01590 | |||
| 75a006ca87 | |||
| cee5880501 | |||
| f65002ea16 | |||
| bd1bfa416c | |||
| 317f96a1bd | |||
| a42d6b954f | |||
| 71b8674664 | |||
| 9e3ca51286 | |||
| 0e6f2b542e | |||
| 218f523022 | |||
| 50c6fb036a | |||
| bc2115ff0a | |||
| 9eee5c2bc0 | |||
| 038163421b | |||
| 7ce58f6e5f | |||
| c6470decb2 | |||
| 8a28639331 | |||
| 65b2b7cb82 | |||
| 2daf71aee4 | |||
| 339edb2295 | |||
| e117b764fb | |||
| ed3096642d | |||
| d51082f651 | |||
| f2fb275b34 | |||
| 95508c4fb7 | |||
| 4677faff38 | |||
| c5f388f6bc | |||
| 4419af427b | |||
| dbdee5fc2c | |||
| 725b3c5eca | |||
| 25f5179b29 | |||
| bf6d084f82 | |||
| 1a03bd9624 | |||
| 6a1d60c5a7 | |||
| 4fef17190f | |||
| 08ca75bb35 | |||
| 143b9c605b | |||
| d76a0271e9 | |||
| 5deb483b94 | |||
| db809f30fe | |||
| dcb50d10c4 | |||
| a409b8b0f7 | |||
| 0512eaa7fd | |||
| a91a67ed8d | |||
| e8df5f9eb4 | |||
| af1257d4ae | |||
| 1f3e568a0d | |||
| c46678c766 | |||
| cb539e82d0 | |||
| 1432d602ba | |||
| 841d2a7010 | |||
| 7cdb48b6c9 | |||
| a667058422 | |||
| 4ffa6bb41b | |||
| 77af16db55 | |||
| 2a44b73056 | |||
| 85d85fa587 | |||
| bd27ed739d | |||
| 3938868115 | |||
| 140792430f | |||
| c04cf1fe2e | |||
| d1d83c84a0 | |||
| 98acc50e13 | |||
| 1a0a02463e | |||
| 00a32c4479 | |||
| 96c499a47e | |||
| f7e8aefeab | |||
| dfa803293f | |||
| 7ade64f855 | |||
| 346e8dcaf0 | |||
| ddfd07bf4a | |||
| a9fe46da0c | |||
| aca1f0d186 | |||
| 9eb415d398 | |||
| 8f6b728534 | |||
| 2e0c09ab39 | |||
| f211344786 | |||
| f8764cdd20 | |||
| 1d17bfd59a | |||
| 98ad6ad366 | |||
| 68702b98f5 | |||
| f93caf277b | |||
| 32db674397 | |||
| e0a7698780 | |||
| 783c74d3ba | |||
| 96d7bc3898 | |||
| 21963c03a2 | |||
| a2a9794fdb | |||
| 879a132077 | |||
| 9650d314c6 | |||
| fcc0c452bb | |||
| 606ebcae92 | |||
| af10ae9e34 | |||
| a23c150738 | |||
| 085a678266 | |||
| c73fb6144b | |||
| bfd201efcc | |||
| 5a2b4f031b | |||
| cf7cafeb4c | |||
| 870657affa | |||
| fe11d4770d | |||
| ac75d8148d | |||
| 4a32cddf08 | |||
| 7461e7c55b | |||
| c8fe9030c7 | |||
| 2ae236e98d | |||
| 802fb95784 | |||
| 0297fdb32f | |||
| 5bede4bf9f | |||
| d37106576d | |||
| ed0f0f7942 | |||
| 3d81c73495 | |||
| e7a540e717 | |||
| bb886c237e | |||
| 6c1e271fa8 | |||
| 4c1b807e4f | |||
| 3b22c0cdd7 | |||
| 31d8f49d3b | |||
| 631404743f | |||
| 1e154e8bc9 | |||
| d5c9639170 | |||
| b90cccbfff | |||
| 94b7c36d62 | |||
| 22f0641c54 | |||
| e465a937c5 | |||
| d2164bc94d | |||
| df9d09725b | |||
| 1ffdd1abd1 | |||
| a06de1b165 | |||
| 0a56f46b12 | |||
| 972f9b3546 | |||
| 0fd3af6828 | |||
| fafb207799 | |||
| b1aea424e8 | |||
| 3598acaddc | |||
| 8e03a1ffca | |||
| ded8afa8fc | |||
| dcd2b1eb6b | |||
| c04ef47be3 | |||
| 62f3c87e8a | |||
| 1b9776ecfb | |||
| 7b1efa718e | |||
| f60ad15f70 | |||
| 28ab176466 | |||
| 3f3db006e7 | |||
| 7801cdf9ff | |||
| 836e1bba54 | |||
| de9c5b88ab | |||
| 77981f889f | |||
| 0a132ed5ed | |||
| 5a953761b0 | |||
| 27ee192c8f | |||
| dfa58183c6 | |||
| e8668f3ed4 | |||
| c84e3dac38 | |||
| 72ab51ea60 | |||
| 1bfb63fe86 | |||
| 2cf68ab263 | |||
| 215bc64a83 | |||
| 1b17f4e9df | |||
| 73f0b1992d | |||
| 21f54dd4ff | |||
| a5903ec419 | |||
| ac496b0cf6 | |||
| 6036136938 | |||
| a9c7a7a405 | |||
| ce8286dadd | |||
| 532b177d2e | |||
| 504aac0350 | |||
| 454aad2170 | |||
| fd0cb7da23 | |||
| 4093fd9b79 | |||
| 3d6f91cbef | |||
| fffd508bb2 | |||
| f4eb37d44d | |||
| c79aaa9c48 | |||
| e3bc6f148a | |||
| a43bd13e6a | |||
| 6aa00c52dc | |||
| 333b35d8b9 | |||
| 30d5bfa7b4 | |||
| 890673a197 | |||
| 6344ad28aa | |||
| eadc3c8c5a | |||
| 9b8db111dd | |||
| 7b506fadc6 | |||
| 27539d4aad | |||
| 1ce44565a3 | |||
| e70e651901 | |||
| 00b0515fc1 | |||
| d8c04b1f67 | |||
| 172ef8c379 | |||
| 7e1f045c09 | |||
| d2fdf7b647 | |||
| e1942d96d0 | |||
| 496e6c1711 | |||
| c9fc0fbed1 | |||
| 3121ea6111 | |||
| 59ecc6e109 | |||
| eb42b9a4b6 | |||
| 82660cf6af | |||
| 54afd3d954 | |||
| 9ee3471153 | |||
| 691c13d1e1 | |||
| f7f23015d0 | |||
| e432b7061d | |||
| 241ccf00a5 | |||
| 1a0046df95 | |||
| 30f63eefb3 | |||
| 6114193fd5 | |||
| 82420605ef | |||
| 3bddceb17b | |||
| a2ca753dd9 | |||
| 6f516a15aa | |||
| 223ed41c53 | |||
| d2a3932626 | |||
| 27fab61646 | |||
| 05f8870424 | |||
| 4a829154db | |||
| f8073f429f | |||
| 0a3220df85 | |||
| 04d37c590b | |||
| 9a57f463ce | |||
| ab14b65078 | |||
| fdfae0f78a | |||
| 9ebe7f683a | |||
| 185af08e75 | |||
| 874c679bfe | |||
| 76a6449ffa | |||
| fd8e200bd7 | |||
| aa7e739b0e | |||
| 97f379ff44 | |||
| 3904f9c503 | |||
| 7753993987 | |||
| fc92d40b3a | |||
| 8f48da8bb0 | |||
| aba325e109 | |||
| 2dd31f0f05 | |||
| d42d96e166 | |||
| 3571c238b4 | |||
| 2087332b69 | |||
| dc71f9cd5e | |||
| 99ed4d6cb9 | |||
| 3646cfb47e | |||
| 1b7ce8bcde | |||
| 89c84676dd | |||
| 1c7b374c42 | |||
| 7100a00ef1 | |||
| df04100ff6 | |||
| b893df035b | |||
| 67c6146f96 | |||
| 6439e2fdd0 | |||
| 13aa615745 | |||
| b8c0d4c4ea | |||
| 6992b0319a | |||
| d1111009e3 | |||
| 6c624ca08a | |||
| 1722831bf5 | |||
| 5291558b23 | |||
| 8a133938e6 | |||
| c1b3f1977d | |||
| f086156d48 | |||
| 7080013dd6 | |||
| b080825bb2 | |||
| 8bb696bf9a | |||
| 55e8451513 | |||
| 7e4e2a1d5d | |||
| 5027757760 | |||
| d4d040d9ec | |||
| 4f1b76f5ff | |||
| 3b3eda5bfc | |||
| 79d4956b75 | |||
| becc07c2bd | |||
| 9acfd8f5d2 | |||
| 0b530ce181 | |||
| 402835d72d | |||
| 08d579ec87 | |||
| 8b92755487 | |||
| 01b48107f3 | |||
| a546803970 | |||
| 96c28c2611 | |||
| 65a22417f7 | |||
| 6c271e7af9 | |||
| 5841377431 | |||
| a85cafe7ab | |||
| 41d91ae791 | |||
| dca5a26fe4 | |||
| 7e8f6d391f | |||
| 7aa00ee6e0 | |||
| 2e027e6195 | |||
| a9c5877e5b | |||
| 337ba4ef34 | |||
| 5d69ec2391 | |||
| 9f9b4d2e84 | |||
| 0f32c2d680 | |||
| 96a18ec8e9 | |||
| 65c39a3117 | |||
| 15150f9a16 | |||
| 259879c964 | |||
| ed87789abe | |||
| 09492fa779 | |||
| 8122c0b352 | |||
| 28f0ab1001 | |||
| 266f82b6c5 | |||
| 813a8956d3 | |||
| 0a8fa2be4d | |||
| 6e347dd32c | |||
| 33c9e2b58d | |||
| 16f8f6036c | |||
| 76b696e3bf | |||
| 7cadbb6398 | |||
| bf22399aba | |||
| 0b9a3ef68a | |||
| f8d6c7e7d0 | |||
| 90ba9a1a3a | |||
| 6815731da1 | |||
| 4d24e7bef8 | |||
| 8d5f7af780 | |||
| 08c8b84a10 | |||
| 52dce66598 | |||
| 255fec84bd | |||
| 9142314d39 | |||
| 27164093ea | |||
| 67312d03d0 | |||
| ad9ae867c0 | |||
| af287c387e | |||
| acf10eeef0 | |||
| 44b90bd4f3 | |||
| 3e558af18f | |||
| 3774d4fc62 | |||
| a24acdb8ce | |||
| f91d5b53c1 | |||
| c053adc9b2 | |||
| e3bc588164 | |||
| 392319d26c | |||
| 584638977c | |||
| be8632db1c | |||
| 094514b91a | |||
| 3c43f4f3c5 | |||
| 12f9392db9 | |||
| d787cb6ad9 | |||
| db02c3b73c | |||
| a10214d82b | |||
| bc61054931 | |||
| 0becdccb68 | |||
| cee92518ea | |||
| a34a8e180d | |||
| f9f48753de | |||
| c9af13df78 | |||
| f66b456d7c | |||
| 6d722c5591 | |||
| 9ed9aef1d3 | |||
| 0cc398130d | |||
| 927f48985e | |||
| 3b31b92f1f | |||
| aaf725a498 | |||
| 36aa166a95 | |||
| e7754d313e |
@@ -0,0 +1,10 @@
|
||||
root=true
|
||||
|
||||
[*]
|
||||
end_of_line = lf
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{cs,cshtml,csx,vb,vbx,vbhtml,fs,fsx,txt,ps1,sql}]
|
||||
indent_size = 4
|
||||
+3
-1
@@ -142,4 +142,6 @@ build/ui-docs.zip
|
||||
build/csharp-docs.zip
|
||||
build/msbuild.log
|
||||
.vs/
|
||||
src/packages/
|
||||
src/packages/
|
||||
build/tools/
|
||||
src/PrecompiledWeb/*
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
[](https://ci.appveyor.com/project/Umbraco/umbraco-cms-hs8dx/branch/dev-v7)
|
||||
|
||||
Umbraco CMS
|
||||
===========
|
||||
The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 390,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
|
||||
|
||||
+46
-3
@@ -113,18 +113,61 @@ REM This is necessary because SETLOCAL is on in InstallGit.cmd so that one might
|
||||
REM but the path setting is lost due to SETLOCAL
|
||||
SET PATH="C:\Program Files (x86)\Git\cmd";"C:\Program Files\Git\cmd";%PATH%
|
||||
|
||||
SET toolsFolder=%CD%\tools\
|
||||
IF NOT EXIST "%toolsFolder%" (
|
||||
MD tools
|
||||
)
|
||||
|
||||
SET nuGetExecutable=%CD%\tools\nuget.exe
|
||||
IF NOT EXIST "%nuGetExecutable%" (
|
||||
ECHO Getting NuGet so we can fetch some tools
|
||||
ECHO Downloading https://dist.nuget.org/win-x86-commandline/latest/nuget.exe to %nuGetExecutable%
|
||||
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', '%nuGetExecutable%')"
|
||||
)
|
||||
|
||||
:: We need 7za.exe for BuildBelle.bat
|
||||
IF NOT EXIST "%toolsFolder%7za.exe" (
|
||||
ECHO 7zip not found - fetching now
|
||||
"%nuGetExecutable%" install 7-Zip.CommandLine -OutputDirectory tools -Verbosity quiet
|
||||
)
|
||||
|
||||
:: We need vswhere.exe for VS2017+
|
||||
IF NOT EXIST "%toolsFolder%vswhere.exe" (
|
||||
ECHO vswhere not found - fetching now
|
||||
"%nuGetExecutable%" install vswhere -OutputDirectory tools -Verbosity quiet
|
||||
)
|
||||
|
||||
:: Put 7za.exe and vswhere.exe in a predictable path (not version specific)
|
||||
FOR /f "delims=" %%A in ('dir "%toolsFolder%7-Zip.CommandLine.*" /b') DO SET "sevenZipExePath=%toolsFolder%%%A\"
|
||||
MOVE "%sevenZipExePath%tools\7za.exe" "%toolsFolder%7za.exe"
|
||||
|
||||
FOR /f "delims=" %%A in ('dir "%toolsFolder%vswhere.*" /b') DO SET "vswhereExePath=%toolsFolder%%%A\"
|
||||
MOVE "%vswhereExePath%tools\vswhere.exe" "%toolsFolder%vswhere.exe"
|
||||
|
||||
ECHO.
|
||||
ECHO Making sure we have a web.config
|
||||
IF NOT EXIST "%CD%\..\src\Umbraco.Web.UI\web.config" COPY "%CD%\..\src\Umbraco.Web.UI\web.Template.config" "%CD%\..\src\Umbraco.Web.UI\web.config"
|
||||
|
||||
for /f "usebackq tokens=1* delims=: " %%i in (`"%CD%\tools\vswhere.exe" -latest -requires Microsoft.Component.MSBuild`) do (
|
||||
if /i "%%i"=="installationPath" set InstallDir=%%j
|
||||
)
|
||||
|
||||
SET VSWherePath="%InstallDir%\MSBuild"
|
||||
|
||||
ECHO.
|
||||
ECHO Visual Studio is installed in: %InstallDir%
|
||||
|
||||
SET MSBUILDPATH=C:\Program Files (x86)\MSBuild\14.0\Bin
|
||||
SET MSBUILD="%MSBUILDPATH%\MsBuild.exe"
|
||||
|
||||
ECHO.
|
||||
ECHO Reporting NuGet version
|
||||
"%CD%\..\src\.nuget\NuGet.exe" help | findstr "^NuGet Version:"
|
||||
"%nuGetExecutable%" help | findstr "^NuGet Version:"
|
||||
|
||||
ECHO.
|
||||
ECHO Restoring NuGet packages
|
||||
ECHO Into %nuGetFolder%
|
||||
"%CD%\..\src\.nuget\NuGet.exe" restore "%CD%\..\src\umbraco.sln" -Verbosity Quiet -NonInteractive -PackagesDirectory "%nuGetFolder%"
|
||||
"%nuGetExecutable%" restore "%CD%\..\src\umbraco.sln" -Verbosity Quiet -NonInteractive -PackagesDirectory "%nuGetFolder%"
|
||||
IF ERRORLEVEL 1 GOTO :error
|
||||
|
||||
ECHO.
|
||||
@@ -134,7 +177,7 @@ ECHO This takes a few minutes and logging is set to report warnings
|
||||
ECHO and errors only so it might seems like nothing is happening for a while.
|
||||
ECHO You can check the msbuild.log file for progress.
|
||||
ECHO.
|
||||
%MSBUILD% "Build.proj" /p:BUILD_RELEASE=%RELEASE% /p:BUILD_COMMENT=%COMMENT% /p:NugetPackagesDirectory="%nuGetFolder%" /consoleloggerparameters:Summary;ErrorsOnly /fileLogger
|
||||
%MSBUILD% "Build.proj" /p:BUILD_RELEASE=%RELEASE% /p:BUILD_COMMENT=%COMMENT% /p:NugetPackagesDirectory="%nuGetFolder%" /p:VSWherePath=%VSWherePath% /consoleloggerparameters:Summary;ErrorsOnly /fileLogger
|
||||
IF ERRORLEVEL 1 GOTO error
|
||||
|
||||
ECHO.
|
||||
|
||||
+48
-22
@@ -1,33 +1,59 @@
|
||||
@ECHO OFF
|
||||
SETLOCAL
|
||||
:: SETLOCAL is on, so changes to the path not persist to the actual user's path
|
||||
|
||||
SET release=%1
|
||||
ECHO Installing Npm NuGet Package
|
||||
|
||||
SET nuGetFolder=%CD%\..\src\packages\
|
||||
ECHO Configured packages folder: %nuGetFolder%
|
||||
SET toolsFolder=%CD%\tools\
|
||||
ECHO Current folder: %CD%
|
||||
|
||||
%CD%\..\src\.nuget\NuGet.exe install Npm.js -OutputDirectory %nuGetFolder% -Verbosity quiet
|
||||
SET nodeFileName=node-v6.9.1-win-x86.7z
|
||||
SET nodeExtractFolder=%toolsFolder%node.js.691
|
||||
|
||||
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\"
|
||||
IF NOT EXIST "%nodeExtractFolder%" (
|
||||
ECHO Downloading http://nodejs.org/dist/v6.9.1/%nodeFileName% to %toolsFolder%%nodeFileName%
|
||||
powershell -Command "(New-Object Net.WebClient).DownloadFile('http://nodejs.org/dist/v6.9.1/%nodeFileName%', '%toolsFolder%%nodeFileName%')"
|
||||
ECHO Extracting %nodeFileName% to %nodeExtractFolder%
|
||||
"%toolsFolder%\7za.exe" x "%toolsFolder%\%nodeFileName%" -o"%nodeExtractFolder%" -aos > nul
|
||||
)
|
||||
FOR /f "delims=" %%A in ('dir "%nodeExtractFolder%\node*" /b') DO SET "nodePath=%nodeExtractFolder%\%%A"
|
||||
|
||||
ECHO Adding Npm and Node to path
|
||||
REM SETLOCAL is on, so changes to the path not persist to the actual user's path
|
||||
PATH=%npmPath%;%nodePath%;%PATH%
|
||||
|
||||
SET buildFolder=%CD%
|
||||
SET nuGetExecutable=%CD%\tools\nuget.exe
|
||||
IF NOT EXIST "%nuGetExecutable%" (
|
||||
ECHO Downloading https://dist.nuget.org/win-x86-commandline/latest/nuget.exe to %nuGetExecutable%
|
||||
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://dist.nuget.org/win-x86-commandline/latest/nuget.exe', '%nuGetExecutable%')"
|
||||
)
|
||||
|
||||
ECHO Change directory to %CD%\..\src\Umbraco.Web.UI.Client\
|
||||
CD %CD%\..\src\Umbraco.Web.UI.Client\
|
||||
SET drive=%CD:~0,2%
|
||||
SET nuGetFolder=%drive%\packages\
|
||||
FOR /f "delims=" %%A in ('dir "%nuGetFolder%npm.*" /b') DO SET "npmPath=%nuGetFolder%%%A\"
|
||||
|
||||
ECHO Do npm install and the grunt build of Belle
|
||||
call npm cache clean --quiet
|
||||
call npm install --quiet
|
||||
call npm install -g grunt-cli --quiet
|
||||
call npm install -g bower --quiet
|
||||
call grunt build --buildversion=%release%
|
||||
IF [%npmPath%] == [] GOTO :installnpm
|
||||
IF NOT [%npmPath%] == [] GOTO :build
|
||||
|
||||
ECHO Move back to the build folder
|
||||
CD %buildFolder%
|
||||
:installnpm
|
||||
ECHO Downloading npm
|
||||
ECHO Configured packages folder: %nuGetFolder%
|
||||
ECHO Installing Npm NuGet Package
|
||||
"%nuGetExecutable%" install Npm -OutputDirectory %nuGetFolder% -Verbosity detailed
|
||||
REM Ensures that we look for the just downloaded NPM, not whatever the user has installed on their machine
|
||||
FOR /f "delims=" %%A in ('dir %nuGetFolder%npm.* /b') DO SET "npmPath=%nuGetFolder%%%A\"
|
||||
GOTO :build
|
||||
|
||||
:build
|
||||
ECHO Adding Npm and Node to path
|
||||
REM SETLOCAL is on, so changes to the path not persist to the actual user's 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 cache clean --quiet
|
||||
call npm install --quiet
|
||||
call npm install -g grunt-cli --quiet
|
||||
call npm install -g bower --quiet
|
||||
call grunt build --buildversion=%release%
|
||||
|
||||
ECHO Move back to the build folder
|
||||
CD "%buildFolder%"
|
||||
@@ -57,6 +57,20 @@ $IndexPath = "../src/umbraco.web.ui.client/docs/api/index.html"
|
||||
|
||||
# Build the solution in debug mode
|
||||
$SolutionPath = Join-Path -Path $SolutionRoot -ChildPath "umbraco.sln"
|
||||
|
||||
# Go get nuget.exe if we don't hae it
|
||||
$NuGet = "$ToolsRoot\nuget.exe"
|
||||
$FileExists = Test-Path $NuGet
|
||||
If ($FileExists -eq $False) {
|
||||
Write-Host "Retrieving nuget.exe..."
|
||||
$SourceNugetExe = "https://dist.nuget.org/win-x86-commandline/latest/nuget.exe"
|
||||
Invoke-WebRequest $SourceNugetExe -OutFile $NuGet
|
||||
}
|
||||
|
||||
#restore nuget packages
|
||||
Write-Host "Restoring nuget packages..."
|
||||
& $NuGet restore $SolutionPath
|
||||
|
||||
& $MSBuild "$SolutionPath" /p:Configuration=Debug /maxcpucount /t:Clean
|
||||
if (-not $?)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata>
|
||||
<metadata minClientVersion="3.4.4">
|
||||
<id>UmbracoCms.Core</id>
|
||||
<version>7.0.0</version>
|
||||
<title>Umbraco Cms Core Binaries</title>
|
||||
@@ -14,12 +14,13 @@
|
||||
<summary>Contains the core assemblies needed to run Umbraco Cms</summary>
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<!--Must be this way because 2.0.5 is actually 1.2.15.0 and 2.0.6 is actually 2.0.6 !-->
|
||||
<dependency id="log4net" version="[2.0.5,2.0.6)" />
|
||||
<dependencies>
|
||||
<dependency id="log4net" version="[2.0.8,3.0.0)" />
|
||||
<dependency id="Log4Net.Async" version="[2.0.4,3.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.3,6.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.3,6.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.1, 3.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Security.Cookies" version="[3.0.1, 4.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[3.0.1, 4.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[3.0.1, 4.0.0)" />
|
||||
@@ -27,20 +28,19 @@
|
||||
<dependency id="HtmlAgilityPack" version="[1.4.9.5, 2.0.0)" />
|
||||
<dependency id="Lucene.Net" version="[2.9.4.1, 3.0.0.0)" />
|
||||
<dependency id="SharpZipLib" version="[0.86.0, 1.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.9.8, 7.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.9.9, 7.0.0)" />
|
||||
<dependency id="xmlrpcnet" version="[2.5.0, 3.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.9.2, 2.0.0)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
|
||||
<dependency id="AutoMapper" version="[3.3.1, 4.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[9.0.1, 10.0.0)" />
|
||||
<dependency id="Examine" version="[0.1.81, 1.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[2.5.2, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.8.2, 5.0.0)" />
|
||||
<dependency id="semver" version="[1.1.2, 2.0.0)" />
|
||||
<dependency id="UrlRewritingNet" version="[2.0.7, 3.0.0)" />
|
||||
<!-- Markdown can not be updated due to: https://github.com/hey-red/markdownsharp/issues/71#issuecomment-233585487 -->
|
||||
<dependency id="Markdown" version="[1.14.7, 2.0.0)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.6.0, 5.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
|
||||
<dependency id="Examine" version="[0.1.82, 1.0.0)" />
|
||||
<dependency id="ImageProcessor" version="[2.5.3, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.8.3, 5.0.0)" />
|
||||
<dependency id="semver" version="[1.1.2, 3.0.0)" />
|
||||
<!-- Markdown can not be updated due to: https://github.com/hey-red/markdownsharp/issues/71#issuecomment-233585487 -->
|
||||
<dependency id="Markdown" version="[1.14.7, 2.0.0)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.7.0, 5.0.0)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
|
||||
<metadata minClientVersion="2.8">
|
||||
<metadata minClientVersion="3.4.4">
|
||||
<id>UmbracoCms</id>
|
||||
<version>7.0.0</version>
|
||||
<title>Umbraco Cms</title>
|
||||
@@ -16,10 +16,10 @@
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
<dependency id="Newtonsoft.Json" version="[9.0.1, 10.0.0)" />
|
||||
<dependency id="Umbraco.ModelsBuilder" version="[3.0.5, 4.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[10.0.2, 11.0.0)" />
|
||||
<dependency id="Umbraco.ModelsBuilder" version="[3.0.7, 4.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.1, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.3.0, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.3.0, 3.0.0)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
||||
@@ -41,16 +41,6 @@
|
||||
views/dashboard/developer/examinemanagement.html
|
||||
</control>
|
||||
</tab>
|
||||
<tab caption="Health Check" xdt:Transform="InsertIfMissing" xdt:Locator="Match(caption)">
|
||||
<control>
|
||||
views/dashboard/developer/healthcheck.html
|
||||
</control>
|
||||
</tab>
|
||||
<tab caption="Redirect URL Management" xdt:Transform="InsertIfMissing" xdt:Locator="Match(caption)">
|
||||
<control>
|
||||
views/dashboard/developer/redirecturls.html
|
||||
</control>
|
||||
</tab>
|
||||
</section>
|
||||
|
||||
<section alias="StartupMediaDashboardSection" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
|
||||
@@ -80,4 +70,26 @@
|
||||
<tab caption="Change Password" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
<tab caption="Last Edits" xdt:Locator="Match(caption)" xdt:Transform="Remove" />
|
||||
</section>
|
||||
|
||||
<section alias="RedirectUrlManagement" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
|
||||
<areas>
|
||||
<area>content</area>
|
||||
</areas>
|
||||
<tab caption="Redirect URL Management">
|
||||
<control>
|
||||
views/dashboard/developer/redirecturls.html
|
||||
</control>
|
||||
</tab>
|
||||
</section>
|
||||
|
||||
<section alias="UmbracoHealthCheck" xdt:Locator="Match(alias)" xdt:Transform="InsertIfMissing">
|
||||
<areas>
|
||||
<area>developer</area>
|
||||
</areas>
|
||||
<tab caption="Health Check">
|
||||
<control>
|
||||
views/dashboard/developer/healthcheck.html
|
||||
</control>
|
||||
</tab>
|
||||
</section>
|
||||
</dashBoard>
|
||||
@@ -8,8 +8,16 @@
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
Don't forget to build!
|
||||
*** IMPORTANT NOTICE FOR 7.6 UPGRADES ***
|
||||
|
||||
Be sure to read the version specific upgrade information before proceeding:
|
||||
https://our.umbraco.org/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-6-0
|
||||
|
||||
You will most likely need to make some changes to your web.config and you will need to be
|
||||
aware of the breaking changes listed there to see if these affect your installation.
|
||||
|
||||
|
||||
Don't forget to build!
|
||||
|
||||
We've done our best to transform your configuration files but in case something is not quite right: remember we
|
||||
backed up your files in App_Data\NuGetBackup so you can find the original files before they were transformed.
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
<httpRuntime xdt:Transform="InsertIfMissing" />
|
||||
<httpRuntime maxRequestLength="51200" fcnMode="Single" xdt:Transform="SetAttributes(fcnMode,maxRequestLength)" />
|
||||
<httpRuntime targetFramework="4.5" xdt:Locator="Condition(count(@targetFramework) != 1)" xdt:Transform="SetAttributes(targetFramework)" />
|
||||
|
||||
|
||||
<membership defaultProvider="DefaultMembershipProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove" />
|
||||
<roleManager defaultProvider="DefaultRoleProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>
|
||||
<profile defaultProvider="DefaultProfileProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>>
|
||||
@@ -330,6 +330,9 @@
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.Owin.Security')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.Owin.Security.Cookies')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Net.Http.Formatting')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='Microsoft.CodeAnalysis.CSharp')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='log4net')" xdt:Transform="Remove" />
|
||||
<dependentAssembly xdt:Locator="Condition(./_defaultNamespace:assemblyIdentity/@name='System.Data.SqlServerCe')" xdt:Transform="Remove" />
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
@@ -337,7 +340,7 @@
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.4.9.0" newVersion="1.4.9.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.4.9.5" newVersion="1.4.9.5" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
|
||||
@@ -349,7 +352,7 @@
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
@@ -383,6 +386,14 @@
|
||||
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845DCD8080CC91" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1"/>
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
|
||||
@@ -53,7 +53,6 @@ if ($project) {
|
||||
if(Test-Path $umbracoBinFolder\umbraco.providers.dll) { Remove-Item $umbracoBinFolder\umbraco.providers.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\Umbraco.Web.UI.dll) { Remove-Item $umbracoBinFolder\Umbraco.Web.UI.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\UmbracoExamine.dll) { Remove-Item $umbracoBinFolder\UmbracoExamine.dll -Force -Confirm:$false }
|
||||
if(Test-Path $umbracoBinFolder\UrlRewritingNet.UrlRewriter.dll) { Remove-Item $umbracoBinFolder\UrlRewritingNet.UrlRewriter.dll -Force -Confirm:$false }
|
||||
|
||||
# Delete files Umbraco depends upon
|
||||
$amd64Folder = Join-Path $umbracoBinFolder "amd64"
|
||||
|
||||
@@ -34,10 +34,15 @@
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="templates" title="Templates" type="Umbraco.Web.Trees.TemplatesTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="1"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="partialViews" title="Partial Views" silent="false" initialize="true" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.PartialViewsTree, umbraco" sortOrder="2"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
xdt:Transform="SetAttributes()" />
|
||||
|
||||
<add application="settings" alias="partialViews" type="Umbraco.Web.Trees.PartialViewsTree, umbraco"
|
||||
xdt:Locator="Match(application,alias,type)"
|
||||
xdt:Transform="Remove()" />
|
||||
<add application="settings" alias="partialViews" title="Partial Views" silent="false" initialize="true" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.PartialViewsTreeController, umbraco" sortOrder="2"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="InsertIfMissing" />
|
||||
|
||||
<add application="settings" alias="scripts" title="Scripts" type="umbraco.loadScripts, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
@@ -84,9 +89,14 @@
|
||||
<add application="developer" alias="xslt" title="XSLT Files" type="umbraco.loadXslt, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="5"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTree, umbraco" silent="false" initialize="true" sortOrder="6" title="Partial View Macro Files" iconClosed="icon-folder" iconOpen="icon-folder"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
|
||||
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTree, umbraco"
|
||||
xdt:Locator="Match(application,alias,type)"
|
||||
xdt:Transform="Remove()" />
|
||||
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTreeController, umbraco" silent="false" initialize="true" sortOrder="6" title="Partial View Macro Files" iconClosed="icon-folder" iconOpen="icon-folder"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="InsertIfMissing" />
|
||||
|
||||
<add application="developer" alias="python"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="Remove" />
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.6.0
|
||||
alpha073
|
||||
7.6.2
|
||||
@@ -4,7 +4,7 @@
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
@@ -30,6 +30,10 @@
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /></startup></configuration>
|
||||
|
||||
+2
-2
@@ -11,5 +11,5 @@ using System.Resources;
|
||||
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.6.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0-alpha073")]
|
||||
[assembly: AssemblyFileVersion("7.6.2")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.2")]
|
||||
@@ -1,8 +1,6 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Web;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.ObjectResolution;
|
||||
@@ -163,7 +161,9 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public static ApplicationContext Current { get; internal set; }
|
||||
|
||||
// fixme
|
||||
/// <summary>
|
||||
/// Gets the scope provider.
|
||||
/// </summary>
|
||||
internal IScopeProvider ScopeProvider { get { return _databaseContext == null ? null : _databaseContext.ScopeProvider; } }
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -4,12 +4,14 @@ using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using Umbraco.Core;
|
||||
|
||||
[assembly: PreApplicationStartMethod(typeof(BindingRedirects), "Initialize")]
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Manages any assembly binding redirects that cannot be done via config
|
||||
/// Manages any assembly binding redirects that cannot be done via config (i.e. unsigned --> signed assemblies)
|
||||
/// </summary>
|
||||
internal class BindingRedirects
|
||||
public sealed class BindingRedirects
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
@@ -17,8 +19,8 @@ namespace Umbraco.Core
|
||||
AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
||||
}
|
||||
|
||||
private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=null", RegexOptions.Compiled);
|
||||
private const string Log4NetReplacement = "log4net, Version=1.2.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a";
|
||||
private static readonly Regex Log4NetAssemblyPattern = new Regex("log4net, Version=([\\d\\.]+?), Culture=neutral, PublicKeyToken=\\w+$", RegexOptions.Compiled);
|
||||
private const string Log4NetReplacement = "log4net, Version=2.0.8.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a";
|
||||
|
||||
/// <summary>
|
||||
/// This is used to do an assembly binding redirect via code - normally required due to signature changes in assemblies
|
||||
@@ -28,13 +30,12 @@ namespace Umbraco.Core
|
||||
/// <returns></returns>
|
||||
private static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||
{
|
||||
//log4net:
|
||||
// Use regex to match and replace
|
||||
//log4net:
|
||||
if (Log4NetAssemblyPattern.IsMatch(args.Name) && args.Name != Log4NetReplacement)
|
||||
{
|
||||
return Assembly.Load(Log4NetAssemblyPattern.Replace(args.Name, Log4NetReplacement));
|
||||
}
|
||||
|
||||
|
||||
//AutoMapper:
|
||||
// ensure the assembly is indeed AutoMapper and that the PublicKeyToken is null before trying to Load again
|
||||
// do NOT just replace this with 'return Assembly', as it will cause an infinite loop -> stackoverflow
|
||||
|
||||
@@ -26,6 +26,9 @@ namespace Umbraco.Core.Cache
|
||||
|
||||
public DeepCloneRuntimeCacheProvider(IRuntimeCacheProvider innerProvider)
|
||||
{
|
||||
if (innerProvider.GetType() == typeof(DeepCloneRuntimeCacheProvider))
|
||||
throw new InvalidOperationException("A " + typeof(DeepCloneRuntimeCacheProvider) + " cannot wrap another instance of " + typeof(DeepCloneRuntimeCacheProvider));
|
||||
|
||||
InnerProvider = innerProvider;
|
||||
}
|
||||
|
||||
@@ -105,9 +108,11 @@ namespace Umbraco.Core.Cache
|
||||
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
|
||||
if (value == null) return null; // do not store null values (backward compat)
|
||||
|
||||
//Clone/reset to go into the cache
|
||||
return CheckCloneableAndTracksChanges(value);
|
||||
}, timeout, isSliding, priority, removedCallback, dependentFiles);
|
||||
|
||||
//Clone/reset to go out of the cache
|
||||
return CheckCloneableAndTracksChanges(cached);
|
||||
}
|
||||
|
||||
|
||||
@@ -22,12 +22,12 @@ namespace Umbraco.Core.Cache
|
||||
{
|
||||
private static readonly TEntity[] EmptyEntities = new TEntity[0]; // const
|
||||
private readonly RepositoryCachePolicyOptions _options;
|
||||
|
||||
|
||||
public DefaultRepositoryCachePolicy(IRuntimeCacheProvider cache, RepositoryCachePolicyOptions options)
|
||||
: base(cache)
|
||||
{
|
||||
{
|
||||
if (options == null) throw new ArgumentNullException("options");
|
||||
_options = options;
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public override IRepositoryCachePolicy<TEntity, TId> Scoped(IRuntimeCacheProvider runtimeCache, IScope scope)
|
||||
@@ -244,9 +244,7 @@ namespace Umbraco.Core.Cache
|
||||
/// <inheritdoc />
|
||||
public override void ClearAll()
|
||||
{
|
||||
// fixme the cache should NOT contain anything else so we can clean all, can't we?
|
||||
Cache.ClearAllCache();
|
||||
//Cache.ClearCacheByKeySearch(GetEntityTypeCacheKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,10 +18,17 @@ namespace Umbraco.Core.Cache
|
||||
// it is not *that* complicated but then RepositoryBase needs to have a TRepository generic
|
||||
// type parameter and it all becomes convoluted - keeping it simple for the time being.
|
||||
|
||||
// fixme explain
|
||||
/// <summary>
|
||||
/// Creates a scoped version of this cache policy.
|
||||
/// </summary>
|
||||
/// <param name="runtimeCache">The global isolated runtime cache for this policy.</param>
|
||||
/// <param name="scope">The scope.</param>
|
||||
/// <remarks>When a policy is scoped, it means that it has been created with a scoped
|
||||
/// isolated runtime cache, and now it needs to be wrapped into something that can apply
|
||||
/// changes to the global isolated runtime cache.</remarks>
|
||||
IRepositoryCachePolicy<TEntity, TId> Scoped(IRuntimeCacheProvider runtimeCache, IScope scope);
|
||||
|
||||
/// <summary>
|
||||
/// <summary>
|
||||
/// Gets an entity from the cache, else from the repository.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
internal enum ContentXmlStorage
|
||||
{
|
||||
Default,
|
||||
AspNetTemp,
|
||||
EnvironmentTemp
|
||||
}
|
||||
}
|
||||
@@ -18,10 +18,14 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
var appSettings = System.Configuration.ConfigurationManager.AppSettings;
|
||||
LogUncompletedScopes = string.Equals("true", appSettings["Umbraco.CoreDebug.LogUncompletedScopes"], StringComparison.OrdinalIgnoreCase);
|
||||
DumpOnTimeoutThreadAbort = string.Equals("true", appSettings["Umbraco.CoreDebug.DumpOnTimeoutThreadAbort"], StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
// when true, Scope logs the stack trace for any scope that gets disposed without being completed.
|
||||
// this helps troubleshooting rogue scopes that we forget to complete
|
||||
public bool LogUncompletedScopes { get; private set; }
|
||||
// when true, the Logger creates a minidump of w3wp in ~/App_Data/MiniDump whenever it logs
|
||||
// an error due to a ThreadAbortException that is due to a timeout.
|
||||
public bool DumpOnTimeoutThreadAbort { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -517,12 +517,25 @@ namespace Umbraco.Core.Configuration
|
||||
}
|
||||
|
||||
internal static bool ContentCacheXmlStoredInCodeGen
|
||||
{
|
||||
get { return ContentCacheXmlStorageLocation == ContentXmlStorage.AspNetTemp; }
|
||||
}
|
||||
|
||||
internal static ContentXmlStorage ContentCacheXmlStorageLocation
|
||||
{
|
||||
get
|
||||
{
|
||||
//defaults to false
|
||||
return ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLUseLocalTemp")
|
||||
&& bool.Parse(ConfigurationManager.AppSettings["umbracoContentXMLUseLocalTemp"]); //default to false
|
||||
if (ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLStorage"))
|
||||
{
|
||||
return Enum<ContentXmlStorage>.Parse(ConfigurationManager.AppSettings["umbracoContentXMLStorage"]);
|
||||
}
|
||||
if (ConfigurationManager.AppSettings.ContainsKey("umbracoContentXMLUseLocalTemp"))
|
||||
{
|
||||
return bool.Parse(ConfigurationManager.AppSettings["umbracoContentXMLUseLocalTemp"])
|
||||
? ContentXmlStorage.AspNetTemp
|
||||
: ContentXmlStorage.Default;
|
||||
}
|
||||
return ContentXmlStorage.Default;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -139,6 +139,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
internal CommaDelimitedConfigurationElement DisallowedUploadFiles
|
||||
{
|
||||
get { return GetOptionalDelimitedElement("disallowedUploadFiles", new[] {"ashx", "aspx", "ascx", "config", "cshtml", "vbhtml", "asmx", "air", "axd"}); }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("allowedUploadFiles")]
|
||||
internal CommaDelimitedConfigurationElement AllowedUploadFiles
|
||||
{
|
||||
get { return GetOptionalDelimitedElement("allowedUploadFiles", new string[0]); }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("cloneXmlContent")]
|
||||
@@ -177,6 +183,18 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return GetOptionalTextElement("EnableInheritedMediaTypes", true); }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("EnablePropertyValueConverters")]
|
||||
internal InnerTextConfigurationElement<bool> EnablePropertyValueConverters
|
||||
{
|
||||
get { return GetOptionalTextElement("EnablePropertyValueConverters", false); }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("loginBackgroundImage")]
|
||||
internal InnerTextConfigurationElement<string> LoginBackgroundImage
|
||||
{
|
||||
get { return GetOptionalTextElement("loginBackgroundImage", string.Empty); }
|
||||
}
|
||||
|
||||
string IContentSection.NotificationEmailAddress
|
||||
{
|
||||
get { return Notifications.NotificationEmailAddress; }
|
||||
@@ -295,6 +313,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
IEnumerable<string> IContentSection.DisallowedUploadFiles
|
||||
{
|
||||
get { return DisallowedUploadFiles; }
|
||||
}
|
||||
|
||||
IEnumerable<string> IContentSection.AllowedUploadFiles
|
||||
{
|
||||
get { return AllowedUploadFiles; }
|
||||
}
|
||||
|
||||
bool IContentSection.CloneXmlContent
|
||||
@@ -326,5 +349,14 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
get { return EnableInheritedMediaTypes; }
|
||||
}
|
||||
bool IContentSection.EnablePropertyValueConverters
|
||||
{
|
||||
get { return EnablePropertyValueConverters; }
|
||||
}
|
||||
|
||||
string IContentSection.LoginBackgroundImage
|
||||
{
|
||||
get { return LoginBackgroundImage; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
public static class ContentSectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines if file extension is allowed for upload based on (optional) white list and black list
|
||||
/// held in settings.
|
||||
/// Allow upload if extension is whitelisted OR if there is no whitelist and extension is NOT blacklisted.
|
||||
/// </summary>
|
||||
public static bool IsFileAllowedForUpload(this IContentSection contentSection, string extension)
|
||||
{
|
||||
return contentSection.AllowedUploadFiles.Any(x => x.InvariantEquals(extension)) ||
|
||||
(contentSection.AllowedUploadFiles.Any() == false &&
|
||||
contentSection.DisallowedUploadFiles.Any(x => x.InvariantEquals(extension)) == false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,7 +52,9 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
MacroErrorBehaviour MacroErrorBehaviour { get; }
|
||||
|
||||
IEnumerable<string> DisallowedUploadFiles { get; }
|
||||
IEnumerable<string> DisallowedUploadFiles { get; }
|
||||
|
||||
IEnumerable<string> AllowedUploadFiles { get; }
|
||||
|
||||
bool CloneXmlContent { get; }
|
||||
|
||||
@@ -69,5 +71,9 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
bool EnableInheritedDocumentTypes { get; }
|
||||
|
||||
bool EnableInheritedMediaTypes { get; }
|
||||
|
||||
bool EnablePropertyValueConverters { get; }
|
||||
|
||||
string LoginBackgroundImage { get; }
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
Guid Id { get; }
|
||||
string RepositoryUrl { get; }
|
||||
string WebServiceUrl { get; }
|
||||
bool HasCustomWebServiceUrl { get; }
|
||||
bool HasCustomWebServiceUrl { get; }
|
||||
string RestApiUrl { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
public static class RepositoryConfigExtensions
|
||||
{
|
||||
//Our package repo
|
||||
private static readonly Guid RepoGuid = new Guid("65194810-1f85-11dd-bd0b-0800200c9a66");
|
||||
|
||||
public static IRepository GetDefault(this IRepositoriesSection repos)
|
||||
{
|
||||
var found = repos.Repositories.FirstOrDefault(x => x.Id == RepoGuid);
|
||||
if (found == null)
|
||||
throw new InvalidOperationException("No default package repository found with id " + RepoGuid);
|
||||
return found;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -38,9 +38,16 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get
|
||||
{
|
||||
var prop = Properties["webserviceurl"];
|
||||
var repoUrl = this[prop] as ConfigurationElement;
|
||||
return (repoUrl != null && repoUrl.ElementInformation.IsPresent);
|
||||
return (string) prop.DefaultValue != (string) this[prop];
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty("restapiurl", DefaultValue = "https://our.umbraco.org/webapi/packages/v1")]
|
||||
public string RestApiUrl
|
||||
{
|
||||
get { return (string)base["restapiurl"]; }
|
||||
set { base["restapiurl"] = value; }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ namespace Umbraco.Core.Configuration
|
||||
{
|
||||
public class UmbracoVersion
|
||||
{
|
||||
private static readonly Version Version = new Version("7.6.0");
|
||||
private static readonly Version Version = new Version("7.6.2");
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current version of Umbraco.
|
||||
@@ -24,7 +24,7 @@ namespace Umbraco.Core.Configuration
|
||||
/// Gets the version comment (like beta or RC).
|
||||
/// </summary>
|
||||
/// <value>The version comment.</value>
|
||||
public static string CurrentComment { get { return "alpha073"; } }
|
||||
public static string CurrentComment { get { return ""; } }
|
||||
|
||||
// Get the version of the umbraco.dll by looking at a class in that dll
|
||||
// Had to do it like this due to medium trust issues, see: http://haacked.com/archive/2010/11/04/assembly-location-and-medium-trust.aspx
|
||||
|
||||
@@ -89,6 +89,11 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string Media = "B796F64C-1F99-4FFB-B886-4BF4BC011A9C";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Document object.
|
||||
/// </summary>
|
||||
public static readonly Guid MediaGuid = new Guid(Media);
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the Media Recycle Bin.
|
||||
/// </summary>
|
||||
@@ -119,6 +124,11 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string MemberGroup = "366E63B9-880F-4E13-A61C-98069B029728";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Member Group object.
|
||||
/// </summary>
|
||||
public static readonly Guid MemberGroupGuid = new Guid(MemberGroup);
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Member Type object.
|
||||
/// </summary>
|
||||
@@ -148,6 +158,11 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string Template = "6FBDE604-4178-42CE-A10B-8A2600A2F07D";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Template object.
|
||||
/// </summary>
|
||||
public static readonly Guid TemplateTypeGuid = new Guid(Template);
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Lock object.
|
||||
/// </summary>
|
||||
|
||||
@@ -289,11 +289,14 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
[Obsolete("GUIDs are no longer used to reference Property Editors, use the Alias constant instead. This will be removed in future versions")]
|
||||
public const string RelatedLinks = "71B8AD1A-8DC2-425C-B6B8-FAA158075E63";
|
||||
|
||||
[Obsolete("This is an obsoleted picker, use RelatedLinks2Alias instead")]
|
||||
public const string RelatedLinksAlias = "Umbraco.RelatedLinks";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the Related Links datatype.
|
||||
/// Alias for the Related Links property editor.
|
||||
/// </summary>
|
||||
public const string RelatedLinksAlias = "Umbraco.RelatedLinks";
|
||||
public const string RelatedLinks2Alias = "Umbraco.RelatedLinks2";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the Slider datatype.
|
||||
|
||||
@@ -173,7 +173,6 @@ namespace Umbraco.Core
|
||||
return new ServiceContext(
|
||||
new RepositoryFactory(ApplicationCache, ProfilingLogger.Logger, dbContext.SqlSyntax, UmbracoConfig.For.UmbracoSettings()),
|
||||
new PetaPocoUnitOfWorkProvider(scopeProvider),
|
||||
new FileUnitOfWorkProvider(scopeProvider),
|
||||
ApplicationCache,
|
||||
ProfilingLogger.Logger,
|
||||
msgFactory);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Data.SqlServerCe;
|
||||
using System.IO;
|
||||
@@ -34,7 +33,7 @@ namespace Umbraco.Core
|
||||
private string _connectionString;
|
||||
private string _providerName;
|
||||
private DatabaseSchemaResult _result;
|
||||
private DateTime? _connectionLastChecked = null;
|
||||
private DateTime? _connectionLastChecked;
|
||||
|
||||
/// <summary>
|
||||
/// The number of minutes to throttle the checks to CanConnect
|
||||
@@ -99,10 +98,10 @@ namespace Umbraco.Core
|
||||
SqlSyntaxContext.SqlSyntaxProvider = SqlSyntax;
|
||||
|
||||
var asDbFactory2 = factory as IDatabaseFactory2;
|
||||
ScopeProvider = asDbFactory2 == null
|
||||
? new ScopeProvider(new DatabaseFactoryWrapper(factory))
|
||||
ScopeProvider = asDbFactory2 == null
|
||||
? new ScopeProvider(new DatabaseFactoryWrapper(factory))
|
||||
: new ScopeProvider(asDbFactory2);
|
||||
|
||||
|
||||
_logger = logger;
|
||||
_configured = true;
|
||||
}
|
||||
@@ -197,42 +196,13 @@ namespace Umbraco.Core
|
||||
{
|
||||
throw new InvalidOperationException("Cannot create a database instance, there is no available connection string");
|
||||
}
|
||||
|
||||
|
||||
return ScopeProvider.GetAmbientOrNoScope().Database;
|
||||
//var scope = ScopeProvider.AmbientScope;
|
||||
//return scope != null ? scope.Database : ScopeProvider.CreateNoScope().Database;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Replaces the "ambient" database (if any) and by a new temp database.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The returned IDisposable *must* be diposed in order to properly dispose the temp database and
|
||||
/// restore the original "ambient" database (if any).</para>
|
||||
/// <para>This is to be used in background tasks to ensure that they have an "ambient" database which
|
||||
/// will be properly removed from call context and does not interfere with anything else. In most case
|
||||
/// it is not replacing anything, just temporarily installing a database in context.</para>
|
||||
/// </remarks>
|
||||
// fixme - this should just entirely be replaced by Scope?
|
||||
/*
|
||||
public virtual IDisposable UseSafeDatabase(bool force = false)
|
||||
{
|
||||
var factory = _factory as DefaultDatabaseFactory;
|
||||
if (factory == null) throw new NotSupportedException();
|
||||
|
||||
if (DefaultDatabaseFactory.HasAmbientDatabase)
|
||||
{
|
||||
return force
|
||||
? new UsingDatabase(DefaultDatabaseFactory.DetachAmbientDatabase(), factory.CreateDatabase())
|
||||
: new UsingDatabase(null, null);
|
||||
}
|
||||
|
||||
// create a new, temp, database (will be disposed with UsingDatabase)
|
||||
return new UsingDatabase(null, factory.CreateDatabase());
|
||||
}
|
||||
*/
|
||||
|
||||
/// <summary>
|
||||
/// Boolean indicating whether the database has been configured
|
||||
/// </summary>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using umbraco.interfaces;
|
||||
using Umbraco.Core;
|
||||
|
||||
namespace Umbraco.Core.Deploy
|
||||
@@ -8,7 +9,7 @@ namespace Umbraco.Core.Deploy
|
||||
/// <summary>
|
||||
/// Connects to an Umbraco service.
|
||||
/// </summary>
|
||||
public interface IServiceConnector
|
||||
public interface IServiceConnector : IDiscoverable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets an artifact.
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using Umbraco.Core.IO;
|
||||
|
||||
namespace Umbraco.Core.Diagnostics
|
||||
{
|
||||
// taken from https://blogs.msdn.microsoft.com/dondu/2010/10/24/writing-minidumps-in-c/
|
||||
// and https://blogs.msdn.microsoft.com/dondu/2010/10/31/writing-minidumps-from-exceptions-in-c/
|
||||
// which itself got it from http://blog.kalmbach-software.de/2008/12/13/writing-minidumps-in-c/
|
||||
|
||||
internal static class MiniDump
|
||||
{
|
||||
private static readonly object LockO = new object();
|
||||
|
||||
[Flags]
|
||||
public enum Option : uint
|
||||
{
|
||||
// From dbghelp.h:
|
||||
Normal = 0x00000000,
|
||||
WithDataSegs = 0x00000001,
|
||||
WithFullMemory = 0x00000002,
|
||||
WithHandleData = 0x00000004,
|
||||
FilterMemory = 0x00000008,
|
||||
ScanMemory = 0x00000010,
|
||||
WithUnloadedModules = 0x00000020,
|
||||
WithIndirectlyReferencedMemory = 0x00000040,
|
||||
FilterModulePaths = 0x00000080,
|
||||
WithProcessThreadData = 0x00000100,
|
||||
WithPrivateReadWriteMemory = 0x00000200,
|
||||
WithoutOptionalData = 0x00000400,
|
||||
WithFullMemoryInfo = 0x00000800,
|
||||
WithThreadInfo = 0x00001000,
|
||||
WithCodeSegs = 0x00002000,
|
||||
WithoutAuxiliaryState = 0x00004000,
|
||||
WithFullAuxiliaryState = 0x00008000,
|
||||
WithPrivateWriteCopyMemory = 0x00010000,
|
||||
IgnoreInaccessibleMemory = 0x00020000,
|
||||
ValidTypeFlags = 0x0003ffff,
|
||||
}
|
||||
|
||||
//typedef struct _MINIDUMP_EXCEPTION_INFORMATION {
|
||||
// DWORD ThreadId;
|
||||
// PEXCEPTION_POINTERS ExceptionPointers;
|
||||
// BOOL ClientPointers;
|
||||
//} MINIDUMP_EXCEPTION_INFORMATION, *PMINIDUMP_EXCEPTION_INFORMATION;
|
||||
[StructLayout(LayoutKind.Sequential, Pack = 4)] // Pack=4 is important! So it works also for x64!
|
||||
public struct MiniDumpExceptionInformation
|
||||
{
|
||||
public uint ThreadId;
|
||||
public IntPtr ExceptionPointers;
|
||||
[MarshalAs(UnmanagedType.Bool)]
|
||||
public bool ClientPointers;
|
||||
}
|
||||
|
||||
//BOOL
|
||||
//WINAPI
|
||||
//MiniDumpWriteDump(
|
||||
// __in HANDLE hProcess,
|
||||
// __in DWORD ProcessId,
|
||||
// __in HANDLE hFile,
|
||||
// __in MINIDUMP_TYPE DumpType,
|
||||
// __in_opt PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
|
||||
// __in_opt PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
|
||||
// __in_opt PMINIDUMP_CALLBACK_INFORMATION CallbackParam
|
||||
// );
|
||||
|
||||
// Overload requiring MiniDumpExceptionInformation
|
||||
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
|
||||
private static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, ref MiniDumpExceptionInformation expParam, IntPtr userStreamParam, IntPtr callbackParam);
|
||||
|
||||
// Overload supporting MiniDumpExceptionInformation == NULL
|
||||
[DllImport("dbghelp.dll", EntryPoint = "MiniDumpWriteDump", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
|
||||
private static extern bool MiniDumpWriteDump(IntPtr hProcess, uint processId, SafeHandle hFile, uint dumpType, IntPtr expParam, IntPtr userStreamParam, IntPtr callbackParam);
|
||||
|
||||
[DllImport("kernel32.dll", EntryPoint = "GetCurrentThreadId", ExactSpelling = true)]
|
||||
private static extern uint GetCurrentThreadId();
|
||||
|
||||
private static bool Write(SafeHandle fileHandle, Option options, bool withException = false)
|
||||
{
|
||||
var currentProcess = Process.GetCurrentProcess();
|
||||
var currentProcessHandle = currentProcess.Handle;
|
||||
var currentProcessId = (uint)currentProcess.Id;
|
||||
|
||||
MiniDumpExceptionInformation exp;
|
||||
|
||||
exp.ThreadId = GetCurrentThreadId();
|
||||
exp.ClientPointers = false;
|
||||
exp.ExceptionPointers = IntPtr.Zero;
|
||||
|
||||
if (withException)
|
||||
exp.ExceptionPointers = Marshal.GetExceptionPointers();
|
||||
|
||||
var bRet = exp.ExceptionPointers == IntPtr.Zero
|
||||
? MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint) options, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)
|
||||
: MiniDumpWriteDump(currentProcessHandle, currentProcessId, fileHandle, (uint) options, ref exp, IntPtr.Zero, IntPtr.Zero);
|
||||
|
||||
return bRet;
|
||||
}
|
||||
|
||||
public static bool Dump(Option options = Option.WithFullMemory, bool withException = false)
|
||||
{
|
||||
lock (LockO)
|
||||
{
|
||||
// work around "stack trace is not available while minidump debugging",
|
||||
// by making sure a local var (that we can inspect) contains the stack trace.
|
||||
// getting the call stack before it is unwound would require a special exception
|
||||
// filter everywhere in our code = not!
|
||||
var stacktrace = withException ? Environment.StackTrace : string.Empty;
|
||||
|
||||
var filepath = IOHelper.MapPath("~/App_Data/MiniDump");
|
||||
if (Directory.Exists(filepath) == false)
|
||||
Directory.CreateDirectory(filepath);
|
||||
|
||||
var filename = Path.Combine(filepath, string.Format("{0:yyyyMMddTHHmmss}.{1}.dmp", DateTime.UtcNow, Guid.NewGuid().ToString("N").Substring(0, 4)));
|
||||
using (var stream = new FileStream(filename, FileMode.Create, FileAccess.ReadWrite, FileShare.Write))
|
||||
{
|
||||
return Write(stream.SafeFileHandle, options, withException);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool OkToDump()
|
||||
{
|
||||
lock (LockO)
|
||||
{
|
||||
var filepath = IOHelper.MapPath("~/App_Data/MiniDump");
|
||||
if (Directory.Exists(filepath) == false) return true;
|
||||
var count = Directory.GetFiles(filepath, "*.dmp").Length;
|
||||
return count < 8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -295,6 +295,5 @@ namespace Umbraco.Core
|
||||
return list1Groups.Count == list2Groups.Count
|
||||
&& list1Groups.All(g => g.Count() == list2Groups[g.Key].Count());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,85 +1,177 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Security.Permissions;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Event args for a strongly typed object that can support cancellation
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
|
||||
public class CancellableObjectEventArgs<T> : CancellableEventArgs, IEquatable<CancellableObjectEventArgs<T>>
|
||||
{
|
||||
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
|
||||
/// <summary>
|
||||
/// Used as a base class for the generic type CancellableObjectEventArgs{T} so that we can get direct 'object' access to the underlying EventObject
|
||||
/// </summary>
|
||||
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
|
||||
public abstract class CancellableObjectEventArgs : CancellableEventArgs
|
||||
{
|
||||
protected CancellableObjectEventArgs(object eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
|
||||
: base(canCancel, messages, additionalData)
|
||||
{
|
||||
{
|
||||
EventObject = eventObject;
|
||||
}
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages eventMessages)
|
||||
protected CancellableObjectEventArgs(object eventObject, bool canCancel, EventMessages eventMessages)
|
||||
: base(canCancel, eventMessages)
|
||||
{
|
||||
EventObject = eventObject;
|
||||
}
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject, EventMessages eventMessages)
|
||||
protected CancellableObjectEventArgs(object eventObject, EventMessages eventMessages)
|
||||
: this(eventObject, true, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
protected CancellableObjectEventArgs(object eventObject, bool canCancel)
|
||||
: base(canCancel)
|
||||
{
|
||||
EventObject = eventObject;
|
||||
}
|
||||
|
||||
protected CancellableObjectEventArgs(object eventObject)
|
||||
: this(eventObject, true)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the object relating to the event
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is protected so that inheritors can expose it with their own name
|
||||
/// </remarks>
|
||||
internal object EventObject { get; set; }
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event args for a strongly typed object that can support cancellation
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
|
||||
public class CancellableObjectEventArgs<T> : CancellableObjectEventArgs, IEquatable<CancellableObjectEventArgs<T>>
|
||||
{
|
||||
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
|
||||
: base(eventObject, canCancel, messages, additionalData)
|
||||
{
|
||||
}
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject, bool canCancel, EventMessages eventMessages)
|
||||
: base(eventObject, canCancel, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject, EventMessages eventMessages)
|
||||
: base(eventObject, eventMessages)
|
||||
{
|
||||
}
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject, bool canCancel)
|
||||
: base(canCancel)
|
||||
{
|
||||
EventObject = eventObject;
|
||||
}
|
||||
: base(eventObject, canCancel)
|
||||
{
|
||||
}
|
||||
|
||||
public CancellableObjectEventArgs(T eventObject)
|
||||
: this(eventObject, true)
|
||||
{
|
||||
}
|
||||
public CancellableObjectEventArgs(T eventObject)
|
||||
: base(eventObject)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the object relating to the event
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is protected so that inheritors can expose it with their own name
|
||||
/// </remarks>
|
||||
protected T EventObject { get; set; }
|
||||
/// <summary>
|
||||
/// Returns the object relating to the event
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is protected so that inheritors can expose it with their own name
|
||||
/// </remarks>
|
||||
protected new T EventObject
|
||||
{
|
||||
get { return (T) base.EventObject; }
|
||||
set { base.EventObject = value; }
|
||||
}
|
||||
|
||||
public bool Equals(CancellableObjectEventArgs<T> other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return base.Equals(other) && EqualityComparer<T>.Default.Equals(EventObject, other.EventObject);
|
||||
}
|
||||
public bool Equals(CancellableObjectEventArgs<T> other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return base.Equals(other) && EqualityComparer<T>.Default.Equals(EventObject, other.EventObject);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((CancellableObjectEventArgs<T>) obj);
|
||||
}
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((CancellableObjectEventArgs<T>)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (base.GetHashCode() * 397) ^ EqualityComparer<T>.Default.GetHashCode(EventObject);
|
||||
}
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return (base.GetHashCode() * 397) ^ EqualityComparer<T>.Default.GetHashCode(EventObject);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool operator ==(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
|
||||
{
|
||||
return Equals(left, right);
|
||||
}
|
||||
public static bool operator ==(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
|
||||
{
|
||||
return Equals(left, right);
|
||||
}
|
||||
|
||||
public static bool operator !=(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
|
||||
{
|
||||
return !Equals(left, right);
|
||||
}
|
||||
}
|
||||
public static bool operator !=(CancellableObjectEventArgs<T> left, CancellableObjectEventArgs<T> right)
|
||||
{
|
||||
return !Equals(left, right);
|
||||
}
|
||||
}
|
||||
|
||||
[HostProtection(SecurityAction.LinkDemand, SharedState = true)]
|
||||
public class CancellableEnumerableObjectEventArgs<T> : CancellableObjectEventArgs<IEnumerable<T>>, IEquatable<CancellableEnumerableObjectEventArgs<T>>
|
||||
{
|
||||
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, bool canCancel, EventMessages messages, IDictionary<string, object> additionalData)
|
||||
: base(eventObject, canCancel, messages, additionalData)
|
||||
{ }
|
||||
|
||||
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, bool canCancel, EventMessages eventMessages)
|
||||
: base(eventObject, canCancel, eventMessages)
|
||||
{ }
|
||||
|
||||
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, EventMessages eventMessages)
|
||||
: base(eventObject, eventMessages)
|
||||
{ }
|
||||
|
||||
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject, bool canCancel)
|
||||
: base(eventObject, canCancel)
|
||||
{ }
|
||||
|
||||
public CancellableEnumerableObjectEventArgs(IEnumerable<T> eventObject)
|
||||
: base(eventObject)
|
||||
{ }
|
||||
|
||||
public bool Equals(CancellableEnumerableObjectEventArgs<T> other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
|
||||
return EventObject.SequenceEqual(other.EventObject);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (ReferenceEquals(null, obj)) return false;
|
||||
if (ReferenceEquals(this, obj)) return true;
|
||||
if (obj.GetType() != this.GetType()) return false;
|
||||
return Equals((CancellableEnumerableObjectEventArgs<T>)obj);
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return HashCodeHelper.GetHashCode(EventObject);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class DeleteEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<DeleteEventArgs<TEntity>>, IDeletingMediaFilesEventArgs
|
||||
[SupersedeEvent(typeof(SaveEventArgs<>))]
|
||||
[SupersedeEvent(typeof(PublishEventArgs<>))]
|
||||
[SupersedeEvent(typeof(MoveEventArgs<>))]
|
||||
[SupersedeEvent(typeof(CopyEventArgs<>))]
|
||||
public class DeleteEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<DeleteEventArgs<TEntity>>, IDeletingMediaFilesEventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the delete operation
|
||||
@@ -106,7 +111,7 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
return base.Equals(other) && MediaFilesToDelete.Equals(other.MediaFilesToDelete);
|
||||
return base.Equals(other) && MediaFilesToDelete.SequenceEqual(other.MediaFilesToDelete);
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
|
||||
@@ -4,7 +4,7 @@ using System.Xml.Linq;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class ImportEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<ImportEventArgs<TEntity>>
|
||||
public class ImportEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportEventArgs<TEntity>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting an XElement with the xml being imported
|
||||
|
||||
@@ -4,7 +4,7 @@ using Umbraco.Core.Packaging.Models;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
internal class ImportPackageEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<ImportPackageEventArgs<TEntity>>
|
||||
internal class ImportPackageEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<ImportPackageEventArgs<TEntity>>
|
||||
{
|
||||
private readonly MetaData _packageMetaData;
|
||||
|
||||
@@ -32,7 +32,8 @@ namespace Umbraco.Core.Events
|
||||
public bool Equals(ImportPackageEventArgs<TEntity> other)
|
||||
{
|
||||
if (ReferenceEquals(null, other)) return false;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
if (ReferenceEquals(this, other)) return true;
|
||||
//TODO: MetaData for package metadata has no equality operators :/
|
||||
return base.Equals(other) && _packageMetaData.Equals(other._packageMetaData);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,8 +5,10 @@ using System.Linq;
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// This event manager supports event cancellation and will raise the events as soon as they are tracked, it does not store tracked events
|
||||
/// An IEventDispatcher that immediately raise all events.
|
||||
/// </summary>
|
||||
/// <remarks>This means that events will be raised during the scope transaction,
|
||||
/// whatever happens, and the transaction could roll back in the end.</remarks>
|
||||
internal class PassThroughEventDispatcher : IEventDispatcher
|
||||
{
|
||||
public bool DispatchCancelable(EventHandler eventHandler, object sender, CancellableEventArgs args, string eventName = null)
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class PublishEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>, IEquatable<PublishEventArgs<TEntity>>
|
||||
public class PublishEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>, IEquatable<PublishEventArgs<TEntity>>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the publish operation
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
public class SaveEventArgs<TEntity> : CancellableObjectEventArgs<IEnumerable<TEntity>>
|
||||
public class SaveEventArgs<TEntity> : CancellableEnumerableObjectEventArgs<TEntity>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor accepting multiple entities that are used in the saving operation
|
||||
@@ -116,7 +117,5 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
get { return EventObject; }
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,9 @@ using Umbraco.Core.IO;
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// This event manager is created for each scope and is aware of if it is nested in an outer scope
|
||||
/// An IEventDispatcher that queues events, and raise them when the scope
|
||||
/// exits and has been completed.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The outer scope is the only scope that can raise events, the inner scope's will defer to the outer scope
|
||||
/// </remarks>
|
||||
internal class ScopeEventDispatcher : ScopeEventDispatcherBase
|
||||
{
|
||||
public ScopeEventDispatcher()
|
||||
@@ -16,13 +14,17 @@ namespace Umbraco.Core.Events
|
||||
|
||||
protected override void ScopeExitCompleted()
|
||||
{
|
||||
// fixme - we'd need to de-duplicate events somehow, etc - and the deduplication should be last in wins
|
||||
// processing only the last instance of each event...
|
||||
// this is probably far from perfect, because if eg a content is saved in a list
|
||||
// and then as a single content, the two events will probably not be de-duplicated,
|
||||
// but it's better than nothing
|
||||
|
||||
foreach (var e in GetEvents(EventDefinitionFilter.All))
|
||||
foreach (var e in GetEvents(EventDefinitionFilter.LastIn))
|
||||
{
|
||||
e.RaiseEvent();
|
||||
|
||||
// fixme - not sure I like doing it here - but then where? how?
|
||||
// separating concerns means that this should probably not be here,
|
||||
// but then where should it be (without making things too complicated)?
|
||||
var delete = e.Args as IDeletingMediaFilesEventArgs;
|
||||
if (delete != null && delete.MediaFilesToDelete.Count > 0)
|
||||
MediaFileSystem.DeleteMediaFiles(delete.MediaFilesToDelete);
|
||||
@@ -35,13 +37,7 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_mediaFileSystem != null) return _mediaFileSystem;
|
||||
|
||||
// fixme - insane! reading config goes cross AppDomain and serializes context?
|
||||
using (new SafeCallContext())
|
||||
{
|
||||
return _mediaFileSystem = FileSystemProviderManager.Current.MediaFileSystem;
|
||||
}
|
||||
return _mediaFileSystem ?? (_mediaFileSystem = FileSystemProviderManager.Current.MediaFileSystem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,23 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// An IEventDispatcher that queues events.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Can raise, or ignore, cancelable events, depending on option.</para>
|
||||
/// <para>Implementations must override ScopeExitCompleted to define what
|
||||
/// to do with the events when the scope exits and has been completed.</para>
|
||||
/// <para>If the scope exits without being completed, events are ignored.</para>
|
||||
/// </remarks>
|
||||
public abstract class ScopeEventDispatcherBase : IEventDispatcher
|
||||
{
|
||||
//events will be enlisted in the order they are raised
|
||||
private List<IEventDefinition> _events;
|
||||
private readonly bool _raiseCancelable;
|
||||
|
||||
@@ -64,29 +76,263 @@ namespace Umbraco.Core.Events
|
||||
{
|
||||
if (_events == null)
|
||||
return Enumerable.Empty<IEventDefinition>();
|
||||
|
||||
|
||||
switch (filter)
|
||||
{
|
||||
case EventDefinitionFilter.All:
|
||||
return _events;
|
||||
return FilterSupersededAndUpdateToLatestEntity(_events);
|
||||
case EventDefinitionFilter.FirstIn:
|
||||
var l1 = new OrderedHashSet<IEventDefinition>();
|
||||
foreach (var e in _events)
|
||||
{
|
||||
l1.Add(e);
|
||||
}
|
||||
return l1;
|
||||
return FilterSupersededAndUpdateToLatestEntity(l1);
|
||||
case EventDefinitionFilter.LastIn:
|
||||
var l2 = new OrderedHashSet<IEventDefinition>(keepOldest: false);
|
||||
foreach (var e in _events)
|
||||
{
|
||||
l2.Add(e);
|
||||
}
|
||||
return l2;
|
||||
return FilterSupersededAndUpdateToLatestEntity(l2);
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("filter", filter, null);
|
||||
}
|
||||
}
|
||||
|
||||
private class EventDefinitionTypeData
|
||||
{
|
||||
public IEventDefinition EventDefinition { get; set; }
|
||||
public Type EventArgType { get; set; }
|
||||
public SupersedeEventAttribute[] SupersedeAttributes { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will iterate over the events (latest first) and filter out any events or entities in event args that are included
|
||||
/// in more recent events that Supersede previous ones. For example, If an Entity has been Saved and then Deleted, we don't want
|
||||
/// to raise the Saved event (well actually we just don't want to include it in the args for that saved event)
|
||||
/// </summary>
|
||||
/// <param name="events"></param>
|
||||
/// <returns></returns>
|
||||
private static IEnumerable<IEventDefinition> FilterSupersededAndUpdateToLatestEntity(IReadOnlyList<IEventDefinition> events)
|
||||
{
|
||||
//used to keep the 'latest' entity and associated event definition data
|
||||
var allEntities = new List<Tuple<IEntity, EventDefinitionTypeData>>();
|
||||
|
||||
//tracks all CancellableObjectEventArgs instances in the events which is the only type of args we can work with
|
||||
var cancelableArgs = new List<CancellableObjectEventArgs>();
|
||||
|
||||
var result = new List<IEventDefinition>();
|
||||
|
||||
//This will eagerly load all of the event arg types and their attributes so we don't have to continuously look this data up
|
||||
var allArgTypesWithAttributes = events.Select(x => x.Args.GetType())
|
||||
.Distinct()
|
||||
.ToDictionary(x => x, x => x.GetCustomAttributes<SupersedeEventAttribute>(false).ToArray());
|
||||
|
||||
//Iterate all events and collect the actual entities in them and relates them to their corresponding EventDefinitionTypeData
|
||||
//we'll process the list in reverse because events are added in the order they are raised and we want to filter out
|
||||
//any entities from event args that are not longer relevant
|
||||
//(i.e. if an item is Deleted after it's Saved, we won't include the item in the Saved args)
|
||||
for (var index = events.Count - 1; index >= 0; index--)
|
||||
{
|
||||
var eventDefinition = events[index];
|
||||
|
||||
var argType = eventDefinition.Args.GetType();
|
||||
var attributes = allArgTypesWithAttributes[eventDefinition.Args.GetType()];
|
||||
|
||||
var meta = new EventDefinitionTypeData
|
||||
{
|
||||
EventDefinition = eventDefinition,
|
||||
EventArgType = argType,
|
||||
SupersedeAttributes = attributes
|
||||
};
|
||||
|
||||
var args = eventDefinition.Args as CancellableObjectEventArgs;
|
||||
if (args != null)
|
||||
{
|
||||
var list = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject);
|
||||
|
||||
if (list == null)
|
||||
{
|
||||
//extract the event object
|
||||
var obj = args.EventObject as IEntity;
|
||||
if (obj != null)
|
||||
{
|
||||
//Now check if this entity already exists in other event args that supersede this current event arg type
|
||||
if (IsFiltered(obj, meta, allEntities) == false)
|
||||
{
|
||||
//if it's not filtered we can adde these args to the response
|
||||
cancelableArgs.Add(args);
|
||||
result.Add(eventDefinition);
|
||||
//track the entity
|
||||
allEntities.Add(Tuple.Create(obj, meta));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//Can't retrieve the entity so cant' filter or inspect, just add to the output
|
||||
result.Add(eventDefinition);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var toRemove = new List<IEntity>();
|
||||
foreach (var entity in list)
|
||||
{
|
||||
//extract the event object
|
||||
var obj = entity as IEntity;
|
||||
if (obj != null)
|
||||
{
|
||||
//Now check if this entity already exists in other event args that supersede this current event arg type
|
||||
if (IsFiltered(obj, meta, allEntities))
|
||||
{
|
||||
//track it to be removed
|
||||
toRemove.Add(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
//track the entity, it's not filtered
|
||||
allEntities.Add(Tuple.Create(obj, meta));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//we don't need to do anything here, we can't cast to IEntity so we cannot filter, so it will just remain in the list
|
||||
}
|
||||
}
|
||||
|
||||
//remove anything that has been filtered
|
||||
foreach (var entity in toRemove)
|
||||
{
|
||||
list.Remove(entity);
|
||||
}
|
||||
|
||||
//track the event and include in the response if there's still entities remaining in the list
|
||||
if (list.Count > 0)
|
||||
{
|
||||
if (toRemove.Count > 0)
|
||||
{
|
||||
//re-assign if the items have changed
|
||||
args.EventObject = list;
|
||||
}
|
||||
cancelableArgs.Add(args);
|
||||
result.Add(eventDefinition);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//it's not a cancelable event arg so we just include it in the result
|
||||
result.Add(eventDefinition);
|
||||
}
|
||||
}
|
||||
|
||||
//Now we'll deal with ensuring that only the latest(non stale) entities are used throughout all event args
|
||||
UpdateToLatestEntities(allEntities, cancelableArgs);
|
||||
|
||||
//we need to reverse the result since we've been adding by latest added events first!
|
||||
result.Reverse();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void UpdateToLatestEntities(IEnumerable<Tuple<IEntity, EventDefinitionTypeData>> allEntities, IEnumerable<CancellableObjectEventArgs> cancelableArgs)
|
||||
{
|
||||
//Now we'll deal with ensuring that only the latest(non stale) entities are used throughout all event args
|
||||
|
||||
var latestEntities = new OrderedHashSet<IEntity>(keepOldest: true);
|
||||
foreach (var entity in allEntities.OrderByDescending(entity => entity.Item1.UpdateDate))
|
||||
{
|
||||
latestEntities.Add(entity.Item1);
|
||||
}
|
||||
|
||||
foreach (var args in cancelableArgs)
|
||||
{
|
||||
var list = TypeHelper.CreateGenericEnumerableFromObject(args.EventObject);
|
||||
if (list == null)
|
||||
{
|
||||
//try to find the args entity in the latest entity - based on the equality operators, this will
|
||||
//match by Id since that is the default equality checker for IEntity. If one is found, than it is
|
||||
//the most recent entity instance so update the args with that instance so we don't emit a stale instance.
|
||||
var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, args.EventObject));
|
||||
if (foundEntity != null)
|
||||
{
|
||||
args.EventObject = foundEntity;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var updated = false;
|
||||
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
//try to find the args entity in the latest entity - based on the equality operators, this will
|
||||
//match by Id since that is the default equality checker for IEntity. If one is found, than it is
|
||||
//the most recent entity instance so update the args with that instance so we don't emit a stale instance.
|
||||
var foundEntity = latestEntities.FirstOrDefault(x => Equals(x, list[i]));
|
||||
if (foundEntity != null)
|
||||
{
|
||||
list[i] = foundEntity;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (updated)
|
||||
{
|
||||
args.EventObject = list;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This will check against all of the processed entity/events (allEntities) to see if this entity already exists in
|
||||
/// event args that supersede the event args being passed in and if so returns true.
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <param name="eventDef"></param>
|
||||
/// <param name="allEntities"></param>
|
||||
/// <returns></returns>
|
||||
private static bool IsFiltered(
|
||||
IEntity entity,
|
||||
EventDefinitionTypeData eventDef,
|
||||
List<Tuple<IEntity, EventDefinitionTypeData>> allEntities)
|
||||
{
|
||||
var argType = eventDef.EventDefinition.Args.GetType();
|
||||
|
||||
//check if the entity is found in any processed event data that could possible supersede this one
|
||||
var foundByEntity = allEntities
|
||||
.Where(x => x.Item2.SupersedeAttributes.Length > 0
|
||||
//if it's the same arg type than it cannot supersede
|
||||
&& x.Item2.EventArgType != argType
|
||||
&& Equals(x.Item1, entity))
|
||||
.ToArray();
|
||||
|
||||
//no args have been processed with this entity so it should not be filtered
|
||||
if (foundByEntity.Length == 0)
|
||||
return false;
|
||||
|
||||
if (argType.IsGenericType)
|
||||
{
|
||||
var supercededBy = foundByEntity
|
||||
.FirstOrDefault(x =>
|
||||
x.Item2.SupersedeAttributes.Any(y =>
|
||||
//if the attribute type is a generic type def then compare with the generic type def of the event arg
|
||||
(y.SupersededEventArgsType.IsGenericTypeDefinition && y.SupersededEventArgsType == argType.GetGenericTypeDefinition())
|
||||
//if the attribute type is not a generic type def then compare with the normal type of the event arg
|
||||
|| (y.SupersededEventArgsType.IsGenericTypeDefinition == false && y.SupersededEventArgsType == argType)));
|
||||
return supercededBy != null;
|
||||
}
|
||||
else
|
||||
{
|
||||
var supercededBy = foundByEntity
|
||||
.FirstOrDefault(x =>
|
||||
x.Item2.SupersedeAttributes.Any(y =>
|
||||
//since the event arg type is not a generic type, then we just compare type 1:1
|
||||
y.SupersededEventArgsType == argType));
|
||||
return supercededBy != null;
|
||||
}
|
||||
}
|
||||
|
||||
public void ScopeExit(bool completed)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// This is used to know if the event arg attributed should supersede another event arg type when
|
||||
/// tracking events for the same entity. If one event args supercedes another then the event args that have been superseded
|
||||
/// will mean that the event will not be dispatched or the args will be filtered to exclude the entity.
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)]
|
||||
internal class SupersedeEventAttribute : Attribute
|
||||
{
|
||||
public Type SupersededEventArgsType { get; private set; }
|
||||
|
||||
public SupersedeEventAttribute(Type supersededEventArgsType)
|
||||
{
|
||||
SupersededEventArgsType = supersededEventArgsType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Exceptions
|
||||
{
|
||||
internal class ConnectionException : Exception
|
||||
{
|
||||
public ConnectionException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace Umbraco.Core.Exceptions
|
||||
public T Operation { get; private set; }
|
||||
|
||||
public DataOperationException(T operation, string message)
|
||||
:base(message)
|
||||
: base(message)
|
||||
{
|
||||
Operation = operation;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a guid-based entity identifier.
|
||||
/// </summary>
|
||||
[TypeConverter(typeof(UdiTypeConverter))]
|
||||
public class GuidUdi : Udi
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -7,32 +6,32 @@ using System.Text;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to create a hash code from multiple objects.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// .Net has a class the same as this: System.Web.Util.HashCodeCombiner and of course it works for all sorts of things
|
||||
/// which we've not included here as we just need a quick easy class for this in order to create a unique
|
||||
/// hash of directories/files to see if they have changed.
|
||||
/// </remarks>
|
||||
internal class HashCodeCombiner
|
||||
{
|
||||
private long _combinedHash = 5381L;
|
||||
/// <summary>
|
||||
/// Used to create a hash code from multiple objects.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// .Net has a class the same as this: System.Web.Util.HashCodeCombiner and of course it works for all sorts of things
|
||||
/// which we've not included here as we just need a quick easy class for this in order to create a unique
|
||||
/// hash of directories/files to see if they have changed.
|
||||
/// </remarks>
|
||||
internal class HashCodeCombiner
|
||||
{
|
||||
private long _combinedHash = 5381L;
|
||||
|
||||
internal void AddInt(int i)
|
||||
{
|
||||
_combinedHash = ((_combinedHash << 5) + _combinedHash) ^ i;
|
||||
}
|
||||
internal void AddInt(int i)
|
||||
{
|
||||
_combinedHash = ((_combinedHash << 5) + _combinedHash) ^ i;
|
||||
}
|
||||
|
||||
internal void AddObject(object o)
|
||||
{
|
||||
AddInt(o.GetHashCode());
|
||||
}
|
||||
internal void AddObject(object o)
|
||||
{
|
||||
AddInt(o.GetHashCode());
|
||||
}
|
||||
|
||||
internal void AddDateTime(DateTime d)
|
||||
{
|
||||
AddInt(d.GetHashCode());
|
||||
}
|
||||
internal void AddDateTime(DateTime d)
|
||||
{
|
||||
AddInt(d.GetHashCode());
|
||||
}
|
||||
|
||||
internal void AddString(string s)
|
||||
{
|
||||
@@ -40,61 +39,61 @@ namespace Umbraco.Core
|
||||
AddInt((StringComparer.InvariantCulture).GetHashCode(s));
|
||||
}
|
||||
|
||||
internal void AddCaseInsensitiveString(string s)
|
||||
{
|
||||
if (s != null)
|
||||
AddInt((StringComparer.InvariantCultureIgnoreCase).GetHashCode(s));
|
||||
}
|
||||
internal void AddCaseInsensitiveString(string s)
|
||||
{
|
||||
if (s != null)
|
||||
AddInt((StringComparer.InvariantCultureIgnoreCase).GetHashCode(s));
|
||||
}
|
||||
|
||||
internal void AddFileSystemItem(FileSystemInfo f)
|
||||
{
|
||||
//if it doesn't exist, don't proceed.
|
||||
if (!f.Exists)
|
||||
return;
|
||||
internal void AddFileSystemItem(FileSystemInfo f)
|
||||
{
|
||||
//if it doesn't exist, don't proceed.
|
||||
if (!f.Exists)
|
||||
return;
|
||||
|
||||
AddCaseInsensitiveString(f.FullName);
|
||||
AddDateTime(f.CreationTimeUtc);
|
||||
AddDateTime(f.LastWriteTimeUtc);
|
||||
|
||||
//check if it is a file or folder
|
||||
var fileInfo = f as FileInfo;
|
||||
if (fileInfo != null)
|
||||
{
|
||||
AddInt(fileInfo.Length.GetHashCode());
|
||||
}
|
||||
|
||||
var dirInfo = f as DirectoryInfo;
|
||||
if (dirInfo != null)
|
||||
{
|
||||
foreach (var d in dirInfo.GetFiles())
|
||||
{
|
||||
AddFile(d);
|
||||
}
|
||||
foreach (var s in dirInfo.GetDirectories())
|
||||
{
|
||||
AddFolder(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
AddCaseInsensitiveString(f.FullName);
|
||||
AddDateTime(f.CreationTimeUtc);
|
||||
AddDateTime(f.LastWriteTimeUtc);
|
||||
|
||||
internal void AddFile(FileInfo f)
|
||||
{
|
||||
AddFileSystemItem(f);
|
||||
}
|
||||
//check if it is a file or folder
|
||||
var fileInfo = f as FileInfo;
|
||||
if (fileInfo != null)
|
||||
{
|
||||
AddInt(fileInfo.Length.GetHashCode());
|
||||
}
|
||||
|
||||
internal void AddFolder(DirectoryInfo d)
|
||||
{
|
||||
AddFileSystemItem(d);
|
||||
}
|
||||
var dirInfo = f as DirectoryInfo;
|
||||
if (dirInfo != null)
|
||||
{
|
||||
foreach (var d in dirInfo.GetFiles())
|
||||
{
|
||||
AddFile(d);
|
||||
}
|
||||
foreach (var s in dirInfo.GetDirectories())
|
||||
{
|
||||
AddFolder(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hex code of the combined hash code
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal string GetCombinedHashCode()
|
||||
{
|
||||
return _combinedHash.ToString("x", CultureInfo.InvariantCulture);
|
||||
}
|
||||
internal void AddFile(FileInfo f)
|
||||
{
|
||||
AddFileSystemItem(f);
|
||||
}
|
||||
|
||||
}
|
||||
internal void AddFolder(DirectoryInfo d)
|
||||
{
|
||||
AddFileSystemItem(d);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the hex code of the combined hash code
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
internal string GetCombinedHashCode()
|
||||
{
|
||||
return _combinedHash.ToString("x", CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,104 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Borrowed from http://stackoverflow.com/a/2575444/694494
|
||||
/// </summary>
|
||||
internal static class HashCodeHelper
|
||||
{
|
||||
public static int GetHashCode<T1, T2>(T1 arg1, T2 arg2)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return 31 * arg1.GetHashCode() + arg2.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T1, T2, T3>(T1 arg1, T2 arg2, T3 arg3)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = arg1.GetHashCode();
|
||||
hash = 31 * hash + arg2.GetHashCode();
|
||||
return 31 * hash + arg3.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T1, T2, T3, T4>(T1 arg1, T2 arg2, T3 arg3,
|
||||
T4 arg4)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = arg1.GetHashCode();
|
||||
hash = 31 * hash + arg2.GetHashCode();
|
||||
hash = 31 * hash + arg3.GetHashCode();
|
||||
return 31 * hash + arg4.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T>(T[] list)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 0;
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (item == null) continue;
|
||||
hash = 31 * hash + item.GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetHashCode<T>(IEnumerable<T> list)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 0;
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (item == null) continue;
|
||||
hash = 31 * hash + item.GetHashCode();
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a hashcode for a collection for that the order of items
|
||||
/// does not matter.
|
||||
/// So {1, 2, 3} and {3, 2, 1} will get same hash code.
|
||||
/// </summary>
|
||||
public static int GetHashCodeForOrderNoMatterCollection<T>(
|
||||
IEnumerable<T> list)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
int hash = 0;
|
||||
int count = 0;
|
||||
foreach (var item in list)
|
||||
{
|
||||
if (item == null) continue;
|
||||
hash += item.GetHashCode();
|
||||
count++;
|
||||
}
|
||||
return 31 * hash + count.GetHashCode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Alternative way to get a hashcode is to use a fluent
|
||||
/// interface like this:<br />
|
||||
/// return 0.CombineHashCode(field1).CombineHashCode(field2).
|
||||
/// CombineHashCode(field3);
|
||||
/// </summary>
|
||||
public static int CombineHashCode<T>(this int hashCode, T arg)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
return 31 * hashCode + arg.GetHashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,8 @@ namespace Umbraco.Core.IO
|
||||
|
||||
private IScopeProviderInternal ScopeProvider
|
||||
{
|
||||
// fixme - 'course this is bad, but enough for now
|
||||
// this is bad, but enough for now, and we'll refactor
|
||||
// in v8 when we'll get rid of this class' singleton
|
||||
// beware: means that we capture the "current" scope provider - take care in tests!
|
||||
get { return ApplicationContext.Current == null ? null : ApplicationContext.Current.ScopeProvider as IScopeProviderInternal; }
|
||||
}
|
||||
|
||||
@@ -4,38 +4,144 @@ using System.IO;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
public interface IFileSystem
|
||||
/// <summary>
|
||||
/// Provides methods allowing the manipulation of files within an Umbraco application.
|
||||
/// </summary>
|
||||
public interface IFileSystem
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets all directories matching the given path.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the directories.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="IEnumerable{String}"/> representing the matched directories.
|
||||
/// </returns>
|
||||
IEnumerable<string> GetDirectories(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified directory.
|
||||
/// </summary>
|
||||
/// <param name="path">The name of the directory to remove.</param>
|
||||
void DeleteDirectory(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified directory and, if indicated, any subdirectories and files in the directory.
|
||||
/// </summary>
|
||||
/// <remarks>Azure blob storage has no real concept of directories so deletion is always recursive.</remarks>
|
||||
/// <param name="path">The name of the directory to remove.</param>
|
||||
/// <param name="recursive">Whether to remove directories, subdirectories, and files in path.</param>
|
||||
void DeleteDirectory(string path, bool recursive);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified directory exists.
|
||||
/// </summary>
|
||||
/// <param name="path">The directory to check.</param>
|
||||
/// <returns>
|
||||
/// <c>True</c> if the directory exists and the user has permission to view it; otherwise <c>false</c>.
|
||||
/// </returns>
|
||||
bool DirectoryExists(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a file to the file system.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the given file.</param>
|
||||
/// <param name="stream">The <see cref="Stream"/> containing the file contents.</param>
|
||||
void AddFile(string path, Stream stream);
|
||||
|
||||
/// <summary>
|
||||
/// Adds a file to the file system.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the given file.</param>
|
||||
/// <param name="stream">The <see cref="Stream"/> containing the file contents.</param>
|
||||
/// <param name="overrideIfExists">Whether to override the file if it already exists.</param>
|
||||
void AddFile(string path, Stream stream, bool overrideIfExists);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all files matching the given path.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the files.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="IEnumerable{String}"/> representing the matched files.
|
||||
/// </returns>
|
||||
IEnumerable<string> GetFiles(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Gets all files matching the given path and filter.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the files.</param>
|
||||
/// <param name="filter">A filter that allows the querying of file extension. <example>*.jpg</example></param>
|
||||
/// <returns>
|
||||
/// The <see cref="IEnumerable{String}"/> representing the matched files.
|
||||
/// </returns>
|
||||
IEnumerable<string> GetFiles(string path, string filter);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a <see cref="Stream"/> representing the file at the gieven path.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the file.</param>
|
||||
/// <returns>
|
||||
/// <see cref="Stream"/>.
|
||||
/// </returns>
|
||||
Stream OpenFile(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes the specified file.
|
||||
/// </summary>
|
||||
/// <param name="path">The name of the file to remove.</param>
|
||||
void DeleteFile(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Determines whether the specified file exists.
|
||||
/// </summary>
|
||||
/// <param name="path">The file to check.</param>
|
||||
/// <returns>
|
||||
/// <c>True</c> if the file exists and the user has permission to view it; otherwise <c>false</c>.
|
||||
/// </returns>
|
||||
bool FileExists(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the application relative path to the file.
|
||||
/// </summary>
|
||||
/// <param name="fullPathOrUrl">The full path or url.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="string"/> representing the relative path.
|
||||
/// </returns>
|
||||
string GetRelativePath(string fullPathOrUrl);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full qualified path to the file.
|
||||
/// </summary>
|
||||
/// <param name="path">The file to return the full path for.</param>
|
||||
/// <returns>
|
||||
/// The <see cref="string"/> representing the full path.
|
||||
/// </returns>
|
||||
string GetFullPath(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Returns the application relative url to the file.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to return the url for.</param>
|
||||
/// <returns>
|
||||
/// <see cref="string"/> representing the relative url.
|
||||
/// </returns>
|
||||
string GetUrl(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the last modified date/time of the file, expressed as a UTC value.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the file.</param>
|
||||
/// <returns>
|
||||
/// <see cref="DateTimeOffset"/>.
|
||||
/// </returns>
|
||||
DateTimeOffset GetLastModified(string path);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the created date/time of the file, expressed as a UTC value.
|
||||
/// </summary>
|
||||
/// <param name="path">The path to the file.</param>
|
||||
/// <returns>
|
||||
/// <see cref="DateTimeOffset"/>.
|
||||
/// </returns>
|
||||
DateTimeOffset GetCreated(string path);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace Umbraco.Core.IO
|
||||
private long _folderCounter;
|
||||
private bool _folderCounterInitialized;
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
private static readonly Dictionary<int, string> DefaultSizes = new Dictionary<int, string>
|
||||
{
|
||||
{ 100, "thumb" },
|
||||
@@ -158,7 +159,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
// ReSharper disable once AssignNullToNotNullAttribute
|
||||
var filepath = UmbracoConfig.For.UmbracoSettings().Content.UploadAllowDirectories
|
||||
? Path.Combine(folder, filename)
|
||||
? Path.Combine(folder, filename).Replace('\\', '/')
|
||||
: folder + "-" + filename;
|
||||
|
||||
return filepath;
|
||||
@@ -263,7 +264,7 @@ namespace Umbraco.Core.IO
|
||||
var filename = Path.GetFileName(sourcepath);
|
||||
var filepath = GetMediaPath(filename, content.Key, propertyType.Key);
|
||||
this.CopyFile(sourcepath, filepath);
|
||||
CopyThumbnails(sourcepath, filepath);
|
||||
|
||||
return filepath;
|
||||
}
|
||||
|
||||
@@ -302,7 +303,7 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
var property = GetProperty(content, propertyTypeAlias);
|
||||
var svalue = property.Value as string;
|
||||
var oldpath = svalue == null ? null : GetRelativePath(svalue); // FIXME DELETE?
|
||||
var oldpath = svalue == null ? null : GetRelativePath(svalue);
|
||||
if (string.IsNullOrWhiteSpace(oldpath) == false && oldpath != filepath)
|
||||
DeleteFile(oldpath, true);
|
||||
property.Value = GetUrl(filepath);
|
||||
@@ -312,29 +313,17 @@ namespace Umbraco.Core.IO
|
||||
}
|
||||
}
|
||||
|
||||
// sets a file for the FileUpload property editor
|
||||
// ie generates thumbnails and populates autofill properties
|
||||
/// <summary>
|
||||
/// Sets a file for the FileUpload property editor and populates autofill properties
|
||||
/// </summary>
|
||||
/// <param name="content"></param>
|
||||
/// <param name="property"></param>
|
||||
/// <param name="filepath"></param>
|
||||
/// <param name="filestream"></param>
|
||||
private void SetUploadFile(IContentBase content, Property property, string filepath, Stream filestream)
|
||||
{
|
||||
// check if file is an image (and supports resizing and thumbnails etc)
|
||||
var extension = Path.GetExtension(filepath);
|
||||
var isImage = IsImageFile(extension);
|
||||
|
||||
// specific stuff for images (thumbnails etc)
|
||||
if (isImage)
|
||||
{
|
||||
using (var image = Image.FromStream(filestream))
|
||||
{
|
||||
// use one image for all
|
||||
GenerateThumbnails(image, filepath, property.PropertyType);
|
||||
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream, image);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// will use filepath for extension, and filestream for length
|
||||
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream);
|
||||
}
|
||||
{
|
||||
// will use filepath for extension, and filestream for length
|
||||
_uploadAutoFillProperties.Populate(content, property.Alias, filepath, filestream);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -401,6 +390,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
// note: this does not find 'custom' thumbnails?
|
||||
// will find _thumb and _big-thumb but NOT _custom?
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public IEnumerable<string> GetThumbnails(string path)
|
||||
{
|
||||
var parentDirectory = Path.GetDirectoryName(path);
|
||||
@@ -421,12 +411,14 @@ namespace Umbraco.Core.IO
|
||||
DeleteThumbnails(path);
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public void DeleteThumbnails(string path)
|
||||
{
|
||||
GetThumbnails(path)
|
||||
.ForEach(x => base.DeleteFile(x));
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public void CopyThumbnails(string sourcePath, string targetPath)
|
||||
{
|
||||
var targetPathBase = Path.GetDirectoryName(targetPath) ?? "";
|
||||
@@ -466,27 +458,6 @@ namespace Umbraco.Core.IO
|
||||
var dir = Path.GetDirectoryName(file);
|
||||
DeleteDirectory(dir, true);
|
||||
}
|
||||
|
||||
// I don't even understand...
|
||||
/*
|
||||
|
||||
var relativeFilePath = GetRelativePath(file); // fixme - should be relative already
|
||||
if (FileExists(relativeFilePath) == false) return;
|
||||
|
||||
var parentDirectory = Path.GetDirectoryName(relativeFilePath);
|
||||
|
||||
// don't want to delete the media folder if not using directories.
|
||||
if (_contentSection.UploadAllowDirectories && parentDirectory != GetRelativePath("/"))
|
||||
{
|
||||
//issue U4-771: if there is a parent directory the recursive parameter should be true
|
||||
DeleteDirectory(parentDirectory, string.IsNullOrEmpty(parentDirectory) == false);
|
||||
}
|
||||
else
|
||||
{
|
||||
DeleteFile(file, true);
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -500,6 +471,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
#region GenerateThumbnails
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public IEnumerable<ResizedImage> GenerateThumbnails(
|
||||
Image image,
|
||||
string filepath,
|
||||
@@ -521,6 +493,7 @@ namespace Umbraco.Core.IO
|
||||
return GenerateThumbnails(image, filepath, additionalSizes);
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public IEnumerable<ResizedImage> GenerateThumbnails(
|
||||
Image image,
|
||||
string filepath,
|
||||
@@ -543,19 +516,21 @@ namespace Umbraco.Core.IO
|
||||
.ToList(); // now
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public IEnumerable<ResizedImage> GenerateThumbnails(
|
||||
Stream filestream,
|
||||
string filepath,
|
||||
PropertyType propertyType)
|
||||
{
|
||||
// get the original image from the original stream
|
||||
if (filestream.CanSeek) filestream.Seek(0, 0); // fixme - what if we cannot seek?
|
||||
if (filestream.CanSeek) filestream.Seek(0, 0);
|
||||
using (var image = Image.FromStream(filestream))
|
||||
{
|
||||
return GenerateThumbnails(image, filepath, propertyType);
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public IEnumerable<ResizedImage> GenerateThumbnails(
|
||||
Image image,
|
||||
string filepath,
|
||||
@@ -577,16 +552,19 @@ namespace Umbraco.Core.IO
|
||||
|
||||
#region GenerateResized - Generate at resized filepath derived from origin filepath
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int maxWidthHeight)
|
||||
{
|
||||
return GenerateResized(originImage, originFilepath, sizeName, maxWidthHeight, -1, -1);
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int fixedWidth, int fixedHeight)
|
||||
{
|
||||
return GenerateResized(originImage, originFilepath, sizeName, -1, fixedWidth, fixedHeight);
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public ResizedImage GenerateResized(Image originImage, string originFilepath, string sizeName, int maxWidthHeight, int fixedWidth, int fixedHeight)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(sizeName))
|
||||
@@ -602,16 +580,19 @@ namespace Umbraco.Core.IO
|
||||
|
||||
#region GenerateResizedAt - Generate at specified resized filepath
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public ResizedImage GenerateResizedAt(Image originImage, string resizedFilepath, int maxWidthHeight)
|
||||
{
|
||||
return GenerateResizedAt(originImage, resizedFilepath, maxWidthHeight, -1, -1);
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public ResizedImage GenerateResizedAt(Image originImage, int fixedWidth, int fixedHeight, string resizedFilepath)
|
||||
{
|
||||
return GenerateResizedAt(originImage, resizedFilepath, -1, fixedWidth, fixedHeight);
|
||||
}
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public ResizedImage GenerateResizedAt(Image originImage, string resizedFilepath, int maxWidthHeight, int fixedWidth, int fixedHeight)
|
||||
{
|
||||
// target dimensions
|
||||
@@ -658,9 +639,6 @@ namespace Umbraco.Core.IO
|
||||
var rect = new Rectangle(0, 0, width, height);
|
||||
graphics.DrawImage(originImage, rect, 0, 0, originImage.Width, originImage.Height, GraphicsUnit.Pixel);
|
||||
|
||||
// copy metadata
|
||||
// fixme - er... no?
|
||||
|
||||
// get an encoder - based upon the file type
|
||||
var extension = (Path.GetExtension(resizedFilepath) ?? "").TrimStart('.').ToLowerInvariant();
|
||||
var encoders = ImageCodecInfo.GetImageEncoders();
|
||||
@@ -723,6 +701,7 @@ namespace Umbraco.Core.IO
|
||||
|
||||
#region Inner classes
|
||||
|
||||
[Obsolete("This should no longer be used, image manipulation should be done via ImageProcessor, Umbraco no longer generates '_thumb' files for media")]
|
||||
public class ResizedImage
|
||||
{
|
||||
public ResizedImage()
|
||||
|
||||
@@ -155,8 +155,10 @@ namespace Umbraco.Core.IO
|
||||
if (directory == null) throw new InvalidOperationException("Could not get directory.");
|
||||
Directory.CreateDirectory(directory); // ensure it exists
|
||||
|
||||
if (stream.CanSeek) // fixme - what else?
|
||||
stream.Seek(0, 0);
|
||||
// if can seek, be safe and go back to start, else...
|
||||
// hope that the stream hasn't been read already
|
||||
if (stream.CanSeek)
|
||||
stream.Seek(0, SeekOrigin.Begin);
|
||||
|
||||
using (var destination = (Stream) File.Create(fullPath))
|
||||
stream.CopyTo(destination);
|
||||
@@ -286,7 +288,9 @@ namespace Umbraco.Core.IO
|
||||
var opath = path;
|
||||
path = EnsureDirectorySeparatorChar(path);
|
||||
|
||||
// fixme - this part should go!
|
||||
// TODO in v8 this should be cleaned up
|
||||
// the first part should probably removed
|
||||
|
||||
// not sure what we are doing here - so if input starts with a (back) slash,
|
||||
// we assume it's not a FS relative path and we try to convert it... but it
|
||||
// really makes little sense?
|
||||
|
||||
@@ -218,11 +218,11 @@ namespace Umbraco.Core.IO
|
||||
var normPath = NormPath(path);
|
||||
var shadows = Nodes.Where(kvp => IsChild(normPath, kvp.Key)).ToArray();
|
||||
var files = filter != null ? _fs.GetFiles(path, filter) : _fs.GetFiles(path);
|
||||
var regexFilter = FilterToRegex(filter);
|
||||
var wildcard = filter == null ? null : new WildcardExpression(filter);
|
||||
return files
|
||||
.Except(shadows.Where(kvp => (kvp.Value.IsFile && kvp.Value.IsDelete) || kvp.Value.IsDir)
|
||||
.Select(kvp => kvp.Key))
|
||||
.Union(shadows.Where(kvp => kvp.Value.IsFile && kvp.Value.IsExist && FilterByRegex(kvp.Key, regexFilter)).Select(kvp => kvp.Key))
|
||||
.Union(shadows.Where(kvp => kvp.Value.IsFile && kvp.Value.IsExist && (wildcard == null || wildcard.IsMatch(kvp.Key))).Select(kvp => kvp.Key))
|
||||
.Distinct();
|
||||
}
|
||||
|
||||
@@ -326,32 +326,65 @@ namespace Umbraco.Core.IO
|
||||
_sfs.AddFile(path, physicalPath, overrideIfExists, copy);
|
||||
Nodes[normPath] = new ShadowNode(false, false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Helper function for filtering keys by Regex if a filter is specified.
|
||||
/// </summary>
|
||||
/// <param name="input"></param>
|
||||
/// <param name="regexFilter"></param>
|
||||
/// <returns></returns>
|
||||
internal static bool FilterByRegex(string input, string regexFilter)
|
||||
{
|
||||
if (regexFilter == null) return true;
|
||||
return regexFilter != string.Empty && Regex.IsMatch(input, regexFilter);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a filter pattern into a Regex pattern
|
||||
/// </summary>
|
||||
/// <param name="pattern"></param>
|
||||
/// <returns></returns>
|
||||
/// <remarks>
|
||||
/// Appending '$' only if not containing wildcard is stupid and broken.
|
||||
/// It is however what seems to be what they're doing in .NET so we need to match the functionality.
|
||||
/// </remarks>
|
||||
internal static string FilterToRegex(string pattern)
|
||||
// copied from System.Web.Util.Wildcard internal
|
||||
internal class WildcardExpression
|
||||
{
|
||||
if (pattern == null) return null;
|
||||
return "^" + Regex.Escape(pattern).Replace("\\*", ".*").Replace("\\?", ".") + (pattern.Contains("*") ? string.Empty : "$");
|
||||
private readonly string _pattern;
|
||||
private readonly bool _caseInsensitive;
|
||||
private Regex _regex;
|
||||
|
||||
private static Regex metaRegex = new Regex("[\\+\\{\\\\\\[\\|\\(\\)\\.\\^\\$]");
|
||||
private static Regex questRegex = new Regex("\\?");
|
||||
private static Regex starRegex = new Regex("\\*");
|
||||
private static Regex commaRegex = new Regex(",");
|
||||
private static Regex slashRegex = new Regex("(?=/)");
|
||||
private static Regex backslashRegex = new Regex("(?=[\\\\:])");
|
||||
|
||||
public WildcardExpression(string pattern, bool caseInsensitive = true)
|
||||
{
|
||||
_pattern = pattern;
|
||||
_caseInsensitive = caseInsensitive;
|
||||
}
|
||||
|
||||
private void EnsureRegex(string pattern)
|
||||
{
|
||||
if (_regex != null) return;
|
||||
|
||||
var options = RegexOptions.None;
|
||||
|
||||
// match right-to-left (for speed) if the pattern starts with a *
|
||||
|
||||
if (pattern.Length > 0 && pattern[0] == '*')
|
||||
options = RegexOptions.RightToLeft | RegexOptions.Singleline;
|
||||
else
|
||||
options = RegexOptions.Singleline;
|
||||
|
||||
// case insensitivity
|
||||
|
||||
if (_caseInsensitive)
|
||||
options |= RegexOptions.IgnoreCase | RegexOptions.CultureInvariant;
|
||||
|
||||
// Remove regex metacharacters
|
||||
|
||||
pattern = metaRegex.Replace(pattern, "\\$0");
|
||||
|
||||
// Replace wildcard metacharacters with regex codes
|
||||
|
||||
pattern = questRegex.Replace(pattern, ".");
|
||||
pattern = starRegex.Replace(pattern, ".*");
|
||||
pattern = commaRegex.Replace(pattern, "\\z|\\A");
|
||||
|
||||
// anchor the pattern at beginning and end, and return the regex
|
||||
|
||||
_regex = new Regex("\\A" + pattern + "\\z", options);
|
||||
}
|
||||
|
||||
public bool IsMatch(string input)
|
||||
{
|
||||
EnsureRegex(_pattern);
|
||||
return _regex.IsMatch(input);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,9 +52,20 @@ namespace Umbraco.Core.IO
|
||||
try
|
||||
{
|
||||
Directory.Delete(dir, true);
|
||||
dir = dir.Substring(0, dir.Length - _shadowPath.Length - 1);
|
||||
if (Directory.EnumerateFileSystemEntries(dir).Any() == false)
|
||||
Directory.Delete(dir, true);
|
||||
|
||||
// shadowPath make be path/to/dir, remove each
|
||||
dir = dir.Replace("/", "\\");
|
||||
var min = IOHelper.MapPath("~/App_Data/TEMP/ShadowFs").Length;
|
||||
var pos = dir.LastIndexOf("\\", StringComparison.OrdinalIgnoreCase);
|
||||
while (pos > min)
|
||||
{
|
||||
dir = dir.Substring(0, pos);
|
||||
if (Directory.EnumerateFileSystemEntries(dir).Any() == false)
|
||||
Directory.Delete(dir, true);
|
||||
else
|
||||
break;
|
||||
pos = dir.LastIndexOf("\\", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Configuration;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
@@ -72,15 +73,28 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
get
|
||||
{
|
||||
if (GlobalSettings.ContentCacheXmlStoredInCodeGen && SystemUtilities.GetCurrentTrustLevel() == AspNetHostingPermissionLevel.Unrestricted)
|
||||
{
|
||||
return Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData\umbraco.config");
|
||||
switch (GlobalSettings.ContentCacheXmlStorageLocation)
|
||||
{
|
||||
case ContentXmlStorage.AspNetTemp:
|
||||
return Path.Combine(HttpRuntime.CodegenDir, @"UmbracoData\umbraco.config");
|
||||
case ContentXmlStorage.EnvironmentTemp:
|
||||
var appDomainHash = HttpRuntime.AppDomainAppId.ToSHA1();
|
||||
var cachePath = Path.Combine(Environment.ExpandEnvironmentVariables("%temp%"), "UmbracoXml",
|
||||
//include the appdomain hash is just a safety check, for example if a website is moved from worker A to worker B and then back
|
||||
// to worker A again, in theory the %temp% folder should already be empty but we really want to make sure that its not
|
||||
// utilizing an old path
|
||||
appDomainHash);
|
||||
return Path.Combine(cachePath, "umbraco.config");
|
||||
case ContentXmlStorage.Default:
|
||||
return IOHelper.ReturnPath("umbracoContentXML", "~/App_Data/umbraco.config");
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
return IOHelper.ReturnPath("umbracoContentXML", "~/App_Data/umbraco.config");
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Use GlobalSettings.ContentCacheXmlStoredInCodeGen instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
internal static bool ContentCacheXmlStoredInCodeGen
|
||||
{
|
||||
get { return GlobalSettings.ContentCacheXmlStoredInCodeGen; }
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Umbraco.Core.Logging
|
||||
/// This is an old/deprecated logger and has been superceded by ParallelForwardingAppender which is included in Umbraco and
|
||||
/// also by AsyncForwardingAppender in the Log4Net.Async library.
|
||||
/// </summary>
|
||||
[Obsolete("This is superceded by the ParallelForwardingAppender, this will be removed in v8")]
|
||||
[Obsolete("This is superceded by the ParallelForwardingAppender, this will be removed in v8, do not use this")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public class AsynchronousRollingFileAppender : RollingFileAppender
|
||||
{
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using System.Web;
|
||||
using log4net;
|
||||
using log4net.Config;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Diagnostics;
|
||||
|
||||
namespace Umbraco.Core.Logging
|
||||
{
|
||||
@@ -56,18 +59,72 @@ namespace Umbraco.Core.Logging
|
||||
internal ILog LoggerFor(object getTypeFromInstance)
|
||||
{
|
||||
if (getTypeFromInstance == null) throw new ArgumentNullException("getTypeFromInstance");
|
||||
|
||||
|
||||
return LogManager.GetLogger(getTypeFromInstance.GetType());
|
||||
}
|
||||
|
||||
|
||||
public void Error(Type callingType, string message, Exception exception)
|
||||
{
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger != null)
|
||||
logger.Error((message), exception);
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null) return;
|
||||
|
||||
var dump = false;
|
||||
|
||||
if (IsTimeoutThreadAbortException(exception))
|
||||
{
|
||||
message += "\r\nThe thread has been aborted, because the request has timed out.";
|
||||
|
||||
// dump if configured, or if stacktrace contains Monitor.ReliableEnter
|
||||
dump = UmbracoConfig.For.CoreDebug().DumpOnTimeoutThreadAbort || IsMonitorEnterThreadAbortException(exception);
|
||||
|
||||
// dump if it is ok to dump (might have a cap on number of dump...)
|
||||
dump &= MiniDump.OkToDump();
|
||||
}
|
||||
|
||||
if (dump)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dumped = MiniDump.Dump(withException: true);
|
||||
message += dumped
|
||||
? "\r\nA minidump was created in App_Data/MiniDump"
|
||||
: "\r\nFailed to create a minidump";
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
message += string.Format("\r\nFailed to create a minidump ({0}: {1})", e.GetType().FullName, e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
logger.Error(message, exception);
|
||||
}
|
||||
|
||||
public void Warn(Type callingType, string message, params Func<object>[] formatItems)
|
||||
private static bool IsMonitorEnterThreadAbortException(Exception exception)
|
||||
{
|
||||
var abort = exception as ThreadAbortException;
|
||||
if (abort == null) return false;
|
||||
|
||||
var stacktrace = abort.StackTrace;
|
||||
return stacktrace.Contains("System.Threading.Monitor.ReliableEnter");
|
||||
}
|
||||
|
||||
private static bool IsTimeoutThreadAbortException(Exception exception)
|
||||
{
|
||||
var abort = exception as ThreadAbortException;
|
||||
if (abort == null) return false;
|
||||
|
||||
if (abort.ExceptionState == null) return false;
|
||||
|
||||
var stateType = abort.ExceptionState.GetType();
|
||||
if (stateType.FullName != "System.Web.HttpApplication+CancelModuleException") return false;
|
||||
|
||||
var timeoutField = stateType.GetField("_timeout", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
if (timeoutField == null) return false;
|
||||
|
||||
return (bool) timeoutField.GetValue(abort.ExceptionState);
|
||||
}
|
||||
|
||||
public void Warn(Type callingType, string message, params Func<object>[] formatItems)
|
||||
{
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||
@@ -82,7 +139,7 @@ namespace Umbraco.Core.Logging
|
||||
if (showHttpTrace && HttpContext.Current != null)
|
||||
{
|
||||
HttpContext.Current.Trace.Warn(callingType.Name, string.Format(message, formatItems.Select(x => x.Invoke()).ToArray()));
|
||||
}
|
||||
}
|
||||
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||
@@ -99,7 +156,7 @@ namespace Umbraco.Core.Logging
|
||||
var logger = LogManager.GetLogger(callingType);
|
||||
if (logger == null || logger.IsWarnEnabled == false) return;
|
||||
var executedParams = formatItems.Select(x => x.Invoke()).ToArray();
|
||||
logger.WarnFormat((message) + ". Exception: " + e, executedParams);
|
||||
logger.WarnFormat((message) + ". Exception: " + e, executedParams);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -13,301 +13,8 @@ namespace Umbraco.Core.Logging
|
||||
/// <remarks>
|
||||
/// Borrowed from https://github.com/cjbhaines/Log4Net.Async - will reference Nuget packages directly in v8
|
||||
/// </remarks>
|
||||
public class ParallelForwardingAppender : AsyncForwardingAppenderBase, IDisposable
|
||||
[Obsolete("Use the Log4Net.Async.ParallelForwardingAppender instead this will be removed in future versions")]
|
||||
public class ParallelForwardingAppender : Log4Net.Async.ParallelForwardingAppender
|
||||
{
|
||||
#region Private Members
|
||||
|
||||
private const int DefaultBufferSize = 1000;
|
||||
private BlockingCollection<LoggingEventContext> _loggingEvents;
|
||||
private CancellationTokenSource _loggingCancelationTokenSource;
|
||||
private CancellationToken _loggingCancelationToken;
|
||||
private Task _loggingTask;
|
||||
private Double _shutdownFlushTimeout = 2;
|
||||
private TimeSpan _shutdownFlushTimespan = TimeSpan.FromSeconds(2);
|
||||
private static readonly Type ThisType = typeof(ParallelForwardingAppender);
|
||||
private volatile bool shutDownRequested;
|
||||
private int? bufferSize = DefaultBufferSize;
|
||||
|
||||
#endregion Private Members
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the number of LoggingEvents that will be buffered. Set to null for unlimited.
|
||||
/// </summary>
|
||||
public override int? BufferSize
|
||||
{
|
||||
get { return bufferSize; }
|
||||
set { bufferSize = value; }
|
||||
}
|
||||
|
||||
public int BufferEntryCount
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_loggingEvents == null) return 0;
|
||||
return _loggingEvents.Count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the time period in which the system will wait for appenders to flush before canceling the background task.
|
||||
/// </summary>
|
||||
public Double ShutdownFlushTimeout
|
||||
{
|
||||
get
|
||||
{
|
||||
return _shutdownFlushTimeout;
|
||||
}
|
||||
set
|
||||
{
|
||||
_shutdownFlushTimeout = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected override string InternalLoggerName
|
||||
{
|
||||
get
|
||||
{
|
||||
{
|
||||
return "ParallelForwardingAppender";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Properties
|
||||
|
||||
#region Startup
|
||||
|
||||
public override void ActivateOptions()
|
||||
{
|
||||
base.ActivateOptions();
|
||||
_shutdownFlushTimespan = TimeSpan.FromSeconds(_shutdownFlushTimeout);
|
||||
StartForwarding();
|
||||
}
|
||||
|
||||
private void StartForwarding()
|
||||
{
|
||||
if (shutDownRequested)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//Create a collection which will block the thread and wait for new entries
|
||||
//if the collection is empty
|
||||
if (BufferSize.HasValue && BufferSize > 0)
|
||||
{
|
||||
_loggingEvents = new BlockingCollection<LoggingEventContext>(BufferSize.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
//No limit on the number of events.
|
||||
_loggingEvents = new BlockingCollection<LoggingEventContext>();
|
||||
}
|
||||
//The cancellation token is used to cancel a running task gracefully.
|
||||
_loggingCancelationTokenSource = new CancellationTokenSource();
|
||||
_loggingCancelationToken = _loggingCancelationTokenSource.Token;
|
||||
_loggingTask = new Task(SubscriberLoop, _loggingCancelationToken);
|
||||
_loggingTask.Start();
|
||||
}
|
||||
|
||||
#endregion Startup
|
||||
|
||||
#region Shutdown
|
||||
|
||||
private void CompleteSubscriberTask()
|
||||
{
|
||||
shutDownRequested = true;
|
||||
if (_loggingEvents == null || _loggingEvents.IsAddingCompleted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
//Don't allow more entries to be added.
|
||||
_loggingEvents.CompleteAdding();
|
||||
//Allow some time to flush
|
||||
Thread.Sleep(_shutdownFlushTimespan);
|
||||
if (!_loggingTask.IsCompleted && !_loggingCancelationToken.IsCancellationRequested)
|
||||
{
|
||||
_loggingCancelationTokenSource.Cancel();
|
||||
//Wait here so that the error logging messages do not get into a random order.
|
||||
//Don't pass the cancellation token because we are not interested
|
||||
//in catching the OperationCanceledException that results.
|
||||
_loggingTask.Wait();
|
||||
}
|
||||
if (!_loggingEvents.IsCompleted)
|
||||
{
|
||||
ForwardInternalError("The buffer was not able to be flushed before timeout occurred.", null, ThisType);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnClose()
|
||||
{
|
||||
CompleteSubscriberTask();
|
||||
base.OnClose();
|
||||
}
|
||||
|
||||
#endregion Shutdown
|
||||
|
||||
#region Appending
|
||||
|
||||
protected override void Append(LoggingEvent loggingEvent)
|
||||
{
|
||||
if (_loggingEvents == null || _loggingEvents.IsAddingCompleted || loggingEvent == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
loggingEvent.Fix = Fix;
|
||||
//In the case where blocking on a full collection, and the task is subsequently completed, the cancellation token
|
||||
//will prevent the entry from attempting to add to the completed collection which would result in an exception.
|
||||
_loggingEvents.Add(new LoggingEventContext(loggingEvent, HttpContext), _loggingCancelationToken);
|
||||
}
|
||||
|
||||
protected override void Append(LoggingEvent[] loggingEvents)
|
||||
{
|
||||
if (_loggingEvents == null || _loggingEvents.IsAddingCompleted || loggingEvents == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var loggingEvent in loggingEvents)
|
||||
{
|
||||
Append(loggingEvent);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Appending
|
||||
|
||||
#region Forwarding
|
||||
|
||||
/// <summary>
|
||||
/// Iterates over a BlockingCollection containing LoggingEvents.
|
||||
/// </summary>
|
||||
private void SubscriberLoop()
|
||||
{
|
||||
Thread.CurrentThread.Name = String.Format("{0} ParallelForwardingAppender Subscriber Task", Name);
|
||||
//The task will continue in a blocking loop until
|
||||
//the queue is marked as adding completed, or the task is canceled.
|
||||
try
|
||||
{
|
||||
//This call blocks until an item is available or until adding is completed
|
||||
foreach (var entry in _loggingEvents.GetConsumingEnumerable(_loggingCancelationToken))
|
||||
{
|
||||
HttpContext = entry.HttpContext;
|
||||
ForwardLoggingEvent(entry.LoggingEvent, ThisType);
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException ex)
|
||||
{
|
||||
//The thread was canceled before all entries could be forwarded and the collection completed.
|
||||
ForwardInternalError("Subscriber task was canceled before completion.", ex, ThisType);
|
||||
//Cancellation is called in the CompleteSubscriberTask so don't call that again.
|
||||
}
|
||||
catch (ThreadAbortException ex)
|
||||
{
|
||||
//Thread abort may occur on domain unload.
|
||||
ForwardInternalError("Subscriber task was aborted.", ex, ThisType);
|
||||
//Cannot recover from a thread abort so complete the task.
|
||||
CompleteSubscriberTask();
|
||||
//The exception is swallowed because we don't want the client application
|
||||
//to halt due to a logging issue.
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//On exception, try to log the exception
|
||||
ForwardInternalError("Subscriber task error in forwarding loop.", ex, ThisType);
|
||||
//Any error in the loop is going to be some sort of extenuating circumstance from which we
|
||||
//probably cannot recover anyway. Complete subscribing.
|
||||
CompleteSubscriberTask();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Forwarding
|
||||
|
||||
#region IDisposable Implementation
|
||||
|
||||
private bool _disposed = false;
|
||||
|
||||
//Implement IDisposable.
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (_loggingTask != null)
|
||||
{
|
||||
if (!(_loggingTask.IsCanceled || _loggingTask.IsCompleted || _loggingTask.IsFaulted))
|
||||
{
|
||||
try
|
||||
{
|
||||
CompleteSubscriberTask();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogLog.Error(ThisType, "Exception Completing Subscriber Task in Dispose Method", ex);
|
||||
}
|
||||
}
|
||||
try
|
||||
{
|
||||
_loggingTask.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogLog.Error(ThisType, "Exception Disposing Logging Task", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_loggingTask = null;
|
||||
}
|
||||
}
|
||||
if (_loggingEvents != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_loggingEvents.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogLog.Error(ThisType, "Exception Disposing BlockingCollection", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_loggingEvents = null;
|
||||
}
|
||||
}
|
||||
if (_loggingCancelationTokenSource != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
_loggingCancelationTokenSource.Dispose();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
LogLog.Error(ThisType, "Exception Disposing CancellationTokenSource", ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
_loggingCancelationTokenSource = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Use C# destructor syntax for finalization code.
|
||||
~ParallelForwardingAppender()
|
||||
{
|
||||
// Simply call Dispose(false).
|
||||
Dispose(false);
|
||||
}
|
||||
|
||||
#endregion IDisposable Implementation
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,14 @@
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Media
|
||||
{
|
||||
public interface IImageUrlProvider
|
||||
// note: because this interface is obsolete is is *not* IDiscoverable, and in case the
|
||||
// PluginManager is asked to find types implementing this interface it will fall back
|
||||
// to a complete scan.
|
||||
|
||||
[Obsolete("IImageUrlProvider is no longer used and will be removed in future versions")]
|
||||
public interface IImageUrlProvider // IDiscoverable
|
||||
{
|
||||
string Name { get; }
|
||||
string GetImageUrlFromMedia(int mediaId, IDictionary<string, string> parameters);
|
||||
|
||||
@@ -1,6 +1,13 @@
|
||||
namespace Umbraco.Core.Media
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Media
|
||||
{
|
||||
public interface IThumbnailProvider
|
||||
// note: because this interface is obsolete is is *not* IDiscoverable, and in case the
|
||||
// PluginManager is asked to find types implementing this interface it will fall back
|
||||
// to a complete scan.
|
||||
|
||||
[Obsolete("Thumbnails are generated by ImageProcessor, use that instead")]
|
||||
public interface IThumbnailProvider // : IDiscoverable
|
||||
{
|
||||
bool CanProvideThumbnail(string fileUrl);
|
||||
string GetThumbnailUrl(string fileUrl);
|
||||
|
||||
@@ -96,8 +96,7 @@ namespace Umbraco.Core.Media
|
||||
/// <param name="propertyTypeAlias">The property type alias.</param>
|
||||
/// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param>
|
||||
/// <param name="filestream">The stream containing the file data.</param>
|
||||
/// <param name="image">The file data as an image object.</param>
|
||||
public void Populate(IContentBase content, string propertyTypeAlias, string filepath, Stream filestream, Image image = null)
|
||||
public void Populate(IContentBase content, string propertyTypeAlias, string filepath, Stream filestream)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException("content");
|
||||
if (propertyTypeAlias == null) throw new ArgumentNullException("propertyTypeAlias");
|
||||
@@ -110,7 +109,7 @@ namespace Umbraco.Core.Media
|
||||
if (autoFillConfig == null) return; // nothing
|
||||
|
||||
// populate
|
||||
Populate(content, autoFillConfig, filepath, filestream, image);
|
||||
Populate(content, autoFillConfig, filepath, filestream);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -158,8 +157,7 @@ namespace Umbraco.Core.Media
|
||||
/// <param name="autoFillConfig"></param>
|
||||
/// <param name="filepath">The filesystem-relative filepath, or null to clear properties.</param>
|
||||
/// <param name="filestream">The stream containing the file data.</param>
|
||||
/// <param name="image">The file data as an image object.</param>
|
||||
public void Populate(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string filepath, Stream filestream, Image image = null)
|
||||
public void Populate(IContentBase content, IImagingAutoFillUploadField autoFillConfig, string filepath, Stream filestream)
|
||||
{
|
||||
if (content == null) throw new ArgumentNullException("content");
|
||||
if (autoFillConfig == null) throw new ArgumentNullException("autoFillConfig");
|
||||
@@ -172,11 +170,7 @@ namespace Umbraco.Core.Media
|
||||
else
|
||||
{
|
||||
var extension = (Path.GetExtension(filepath) ?? "").TrimStart('.');
|
||||
Size? size;
|
||||
if (image == null)
|
||||
size = _mediaFileSystem.IsImageFile(extension) ? (Size?) _mediaFileSystem.GetDimensions(filestream) : null;
|
||||
else
|
||||
size = new Size(image.Width, image.Height);
|
||||
var size = _mediaFileSystem.IsImageFile(extension) ? (Size?)_mediaFileSystem.GetDimensions(filestream) : null;
|
||||
SetProperties(content, autoFillConfig, size, filestream.Length, extension);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
@@ -84,16 +86,64 @@ namespace Umbraco.Core.Models
|
||||
public string Type { get; set; }
|
||||
|
||||
private Type _runtimeType;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns the CLR type based on it's assembly name stored in the config
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Type GetRuntimeType()
|
||||
{
|
||||
return _runtimeType ?? (_runtimeType = System.Type.GetType(Type));
|
||||
}
|
||||
|
||||
if (_runtimeType != null)
|
||||
return _runtimeType;
|
||||
|
||||
_runtimeType = TryGetType(Type);
|
||||
return _runtimeType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used to try to get and cache the tree type
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
internal static Type TryGetType(string type)
|
||||
{
|
||||
try
|
||||
{
|
||||
return ResolvedTypes.GetOrAdd(type, s =>
|
||||
{
|
||||
var result = System.Type.GetType(type);
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
//we need to implement a bit of a hack here due to some trees being renamed and backwards compat
|
||||
var parts = type.Split(new[] {','}, StringSplitOptions.RemoveEmptyEntries);
|
||||
if (parts.Length == 2)
|
||||
{
|
||||
if (parts[1].Trim() == "umbraco" && parts[0].StartsWith("Umbraco.Web.Trees") && parts[0].EndsWith("Controller") == false)
|
||||
{
|
||||
//if it's one of our controllers but it's not suffixed with "Controller" then add it and try again
|
||||
var tempType = parts[0] + "Controller, umbraco";
|
||||
|
||||
result = System.Type.GetType(tempType);
|
||||
if (result != null)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("Could not resolve type");
|
||||
});
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
//swallow, this is our own exception, couldn't find the type
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static readonly ConcurrentDictionary<string, Type> ResolvedTypes = new ConcurrentDictionary<string, Type>();
|
||||
}
|
||||
}
|
||||
@@ -274,6 +274,9 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
public bool HasPublishedVersion { get { return PublishedVersionGuid != default(Guid); } }
|
||||
|
||||
[IgnoreDataMember]
|
||||
internal DateTime PublishedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Changes the Trashed state of the content object
|
||||
/// </summary>
|
||||
|
||||
@@ -7,7 +7,6 @@ using System.Xml.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Media;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Models.Membership;
|
||||
using Umbraco.Core.Services;
|
||||
@@ -42,7 +41,7 @@ namespace Umbraco.Core.Models
|
||||
/// * The item exists and is published
|
||||
/// * A call to ContentService.Save is made
|
||||
/// * The item has not been modified whatsoever apart from changing it's published status from published to saved
|
||||
///
|
||||
///
|
||||
/// In this case, there is no reason to make any database changes at all
|
||||
/// </remarks>
|
||||
internal static bool RequiresSaving(this IContent entity)
|
||||
@@ -62,7 +61,7 @@ namespace Umbraco.Core.Models
|
||||
/// * The item exists and is published
|
||||
/// * A call to ContentService.Save is made
|
||||
/// * The item has not been modified whatsoever apart from changing it's published status from published to saved
|
||||
///
|
||||
///
|
||||
/// In this case, there is no reason to make any database changes at all
|
||||
/// </remarks>
|
||||
internal static bool RequiresSaving(this IContent entity, PublishedState publishedState)
|
||||
@@ -70,7 +69,7 @@ namespace Umbraco.Core.Models
|
||||
var publishedChanged = entity.IsPropertyDirty("Published") && publishedState != PublishedState.Unpublished;
|
||||
//check if any user prop has changed
|
||||
var propertyValueChanged = entity.IsAnyUserPropertyDirty();
|
||||
|
||||
|
||||
//We need to know if any other property apart from Published was changed here
|
||||
//don't create a new version if the published state has changed to 'Save' but no data has actually been changed
|
||||
if (publishedChanged && entity.Published == false && propertyValueChanged == false)
|
||||
@@ -302,9 +301,9 @@ namespace Umbraco.Core.Models
|
||||
return content.Path.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
|
||||
.Contains(recycleBinId.ToInvariantString());
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Removes characters that are not valide XML characters from all entity properties
|
||||
/// Removes characters that are not valide XML characters from all entity properties
|
||||
/// of type string. See: http://stackoverflow.com/a/961504/5018
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
@@ -456,7 +455,7 @@ namespace Umbraco.Core.Models
|
||||
/// <param name="value">The uploaded <see cref="HttpPostedFileBase"/>.</param>
|
||||
public static void SetValue(this IContentBase content, string propertyTypeAlias, HttpPostedFileBase value)
|
||||
{
|
||||
// ensure we get the filename without the path in IE in intranet mode
|
||||
// ensure we get the filename without the path in IE in intranet mode
|
||||
// http://stackoverflow.com/questions/382464/httppostedfile-filename-different-from-ie
|
||||
var filename = value.FileName;
|
||||
var pos = filename.LastIndexOf(@"\", StringComparison.InvariantCulture);
|
||||
@@ -468,10 +467,10 @@ namespace Umbraco.Core.Models
|
||||
if (pos > 0)
|
||||
filename = filename.Substring(pos + 1);
|
||||
|
||||
// get a safe filename - should this be done by MediaHelper?
|
||||
// get a safe & clean filename
|
||||
filename = IOHelper.SafeFileName(filename);
|
||||
if (string.IsNullOrWhiteSpace(filename)) return;
|
||||
filename = filename.ToLower(); // fixme - er... why?
|
||||
filename = filename.ToLower();
|
||||
|
||||
FileSystemProviderManager.Current.MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, value.InputStream);
|
||||
}
|
||||
@@ -513,10 +512,10 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
if (filename == null || filestream == null) return;
|
||||
|
||||
// get a safe filename - should this be done by MediaHelper?
|
||||
// get a safe & clean filename
|
||||
filename = IOHelper.SafeFileName(filename);
|
||||
if (string.IsNullOrWhiteSpace(filename)) return;
|
||||
filename = filename.ToLower(); // fixme - er... why?
|
||||
filename = filename.ToLower();
|
||||
|
||||
FileSystemProviderManager.Current.MediaFileSystem.SetUploadFile(content, propertyTypeAlias, filename, filestream);
|
||||
}
|
||||
@@ -548,7 +547,7 @@ namespace Umbraco.Core.Models
|
||||
#endregion
|
||||
|
||||
#region User/Profile methods
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="IProfile"/> for the Creator of this media item.
|
||||
/// </summary>
|
||||
@@ -623,7 +622,7 @@ namespace Umbraco.Core.Models
|
||||
///// <param name="tagGroup"></param>
|
||||
///// <returns></returns>
|
||||
///// <remarks>
|
||||
///// The tags returned are only relavent for published content & saved media or members
|
||||
///// The tags returned are only relavent for published content & saved media or members
|
||||
///// </remarks>
|
||||
//public static IEnumerable<ITag> GetTags(this IContentBase content, string propertyTypeAlias, string tagGroup = "default")
|
||||
//{
|
||||
|
||||
@@ -1,85 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
//fixme: This whole thing needs to go, it's super hacky and doens't need to exist in the first place
|
||||
internal static class ContentTypeExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Get all descendant content types
|
||||
/// </summary>
|
||||
/// <param name="contentType"></param>
|
||||
/// <param name="contentTypeService"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<IContentTypeBase> Descendants(this IContentTypeBase contentType, IContentTypeService contentTypeService)
|
||||
{
|
||||
if (contentType is IContentType)
|
||||
{
|
||||
var descendants = contentTypeService.GetContentTypeChildren(contentType.Id)
|
||||
.SelectRecursive(type => contentTypeService.GetContentTypeChildren(type.Id));
|
||||
return descendants;
|
||||
}
|
||||
|
||||
if (contentType is IMediaType)
|
||||
{
|
||||
var descendants = contentTypeService.GetMediaTypeChildren(contentType.Id)
|
||||
.SelectRecursive(type => contentTypeService.GetMediaTypeChildren(type.Id));
|
||||
return descendants;
|
||||
}
|
||||
|
||||
//No other content types have children (i.e. member types)
|
||||
return Enumerable.Empty<IContentTypeBase>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all descendant content types
|
||||
/// </summary>
|
||||
/// <param name="contentType"></param>
|
||||
/// <param name="contentTypeService"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<IContentTypeBase> Descendants(this IContentTypeBase contentType, ContentTypeServiceBase contentTypeService)
|
||||
{
|
||||
var cService = contentTypeService as IContentTypeService;
|
||||
|
||||
return cService == null ? Enumerable.Empty<IContentTypeBase>() : contentType.Descendants(cService);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all descendant and self content types
|
||||
/// </summary>
|
||||
/// <param name="contentType"></param>
|
||||
/// <param name="contentTypeService"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<IContentTypeBase> DescendantsAndSelf(this IContentTypeBase contentType, IContentTypeService contentTypeService)
|
||||
{
|
||||
var descendantsAndSelf = new[] { contentType }.Concat(contentType.Descendants(contentTypeService));
|
||||
return descendantsAndSelf;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all descendant and self content types
|
||||
/// </summary>
|
||||
/// <param name="contentType"></param>
|
||||
/// <param name="contentTypeService"></param>
|
||||
/// <returns></returns>
|
||||
public static IEnumerable<IContentTypeBase> DescendantsAndSelf(this IContentTypeBase contentType, ContentTypeServiceBase contentTypeService)
|
||||
{
|
||||
var descendantsAndSelf = new[] { contentType }.Concat(contentType.Descendants(contentTypeService));
|
||||
return descendantsAndSelf;
|
||||
}
|
||||
|
||||
///// <summary>
|
||||
///// Returns the descendant content type Ids for the given content type
|
||||
///// </summary>
|
||||
///// <param name="contentType"></param>
|
||||
///// <returns></returns>
|
||||
//public static IEnumerable<int> DescendantIds(this IContentTypeBase contentType)
|
||||
//{
|
||||
// return ((ContentTypeService) ApplicationContext.Current.Services.ContentTypeService)
|
||||
// .GetDescendantContentTypeIds(contentType.Id);
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -42,6 +42,7 @@ namespace Umbraco.Core.Models
|
||||
public Guid Key { get; set; }
|
||||
public DateTime CreateDate { get; set; }
|
||||
public DateTime UpdateDate { get; set; }
|
||||
public DateTime? DeletedDate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Special case, always return false, this will cause the repositories managing
|
||||
@@ -60,5 +61,7 @@ namespace Umbraco.Core.Models
|
||||
DeepCloneHelper.DeepCloneRefProperties(this, clone);
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -101,6 +101,9 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
set { SetPropertyValueAndDetectChanges(value, ref _updateDate, Ps.Value.UpdateDateSelector); }
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public DateTime? DeletedDate { get; set; }
|
||||
|
||||
internal virtual void ResetIdentity()
|
||||
{
|
||||
_hasIdentity = false;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
/// <summary>
|
||||
/// Marker interface for aggregate roots
|
||||
/// </summary>
|
||||
public interface IAggregateRoot : IEntity
|
||||
public interface IAggregateRoot : IDeletableEntity
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace Umbraco.Core.Models.EntityBase
|
||||
{
|
||||
public interface IDeletableEntity : IEntity
|
||||
{
|
||||
[DataMember]
|
||||
DateTime? DeletedDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ namespace Umbraco.Core.Models.EntityBase
|
||||
/// <summary>
|
||||
/// Guid based Id
|
||||
/// </summary>
|
||||
/// <remarks>The key is currectly used to store the Unique Id from the
|
||||
/// <remarks>The key is currectly used to store the Unique Id from the
|
||||
/// umbracoNode table, which many of the entities are based on.</remarks>
|
||||
[DataMember]
|
||||
Guid Key { get; set; }
|
||||
|
||||
@@ -49,7 +49,10 @@ namespace Umbraco.Core.Models
|
||||
return path
|
||||
.Replace('\\', System.IO.Path.DirectorySeparatorChar)
|
||||
.Replace('/', System.IO.Path.DirectorySeparatorChar);
|
||||
//.TrimStart(System.IO.Path.DirectorySeparatorChar);
|
||||
|
||||
//Don't strip the start - this was a bug fixed in 7.3, see ScriptRepositoryTests.PathTests
|
||||
//.TrimStart(System.IO.Path.DirectorySeparatorChar)
|
||||
//.TrimStart('/');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
{
|
||||
public interface IPartialView : IFile
|
||||
{
|
||||
|
||||
PartialViewType ViewType { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,8 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
using Umbraco.Core.Services;
|
||||
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// Represents a Partial View file
|
||||
/// </summary>
|
||||
@@ -12,14 +10,21 @@ namespace Umbraco.Core.Models
|
||||
[DataContract(IsReference = true)]
|
||||
public class PartialView : File, IPartialView
|
||||
{
|
||||
[Obsolete("Use the ctor that explicitely sets the view type.")]
|
||||
public PartialView(string path)
|
||||
: this(path, null)
|
||||
: this(PartialViewType.PartialView, path, null)
|
||||
{ }
|
||||
|
||||
internal PartialView(string path, Func<File, string> getFileContent)
|
||||
public PartialView(PartialViewType viewType, string path)
|
||||
: this(viewType, path, null)
|
||||
{ }
|
||||
|
||||
internal PartialView(PartialViewType viewType, string path, Func<File, string> getFileContent)
|
||||
: base(path, getFileContent)
|
||||
{ }
|
||||
{
|
||||
ViewType = viewType;
|
||||
}
|
||||
|
||||
internal PartialViewType ViewType { get; set; }
|
||||
public PartialViewType ViewType { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
internal enum PartialViewType : byte
|
||||
public enum PartialViewType : byte
|
||||
{
|
||||
Unknown = 0, // default
|
||||
PartialView = 1,
|
||||
|
||||
@@ -69,6 +69,7 @@ namespace Umbraco.Core.Models
|
||||
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
|
||||
}
|
||||
|
||||
//TODO: Instead of 'new' this should explicitly implement one of the collection interfaces members
|
||||
internal new void Add(PropertyType item)
|
||||
{
|
||||
using (new WriteLock(_addLocker))
|
||||
|
||||
@@ -110,6 +110,12 @@ namespace Umbraco.Core.Models
|
||||
_ruleCollection.Clear();
|
||||
}
|
||||
|
||||
|
||||
internal void ClearRemovedRules()
|
||||
{
|
||||
_removedRules.Clear();
|
||||
}
|
||||
|
||||
[DataMember]
|
||||
public int LoginNodeId
|
||||
{
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
/// <summary>
|
||||
/// The published content enumerable, this model is to allow ToString to be overriden for value converters to support legacy requests for string values
|
||||
/// </summary>
|
||||
public class PublishedContentEnumerable : IEnumerable<IPublishedContent>
|
||||
{
|
||||
/// <summary>
|
||||
/// The items in the collection
|
||||
/// </summary>
|
||||
private readonly IEnumerable<IPublishedContent> _items;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="PublishedContentEnumerable"/> class.
|
||||
/// </summary>
|
||||
/// <param name="publishedContent">
|
||||
/// The published content items
|
||||
/// </param>
|
||||
public PublishedContentEnumerable(IEnumerable<IPublishedContent> publishedContent)
|
||||
{
|
||||
if (publishedContent == null) throw new ArgumentNullException("publishedContent");
|
||||
_items = publishedContent;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The ToString method to convert the objects back to CSV
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The <see cref="string"/>.
|
||||
/// </returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Join(",", _items.Select(x => x.Id));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The get enumerator.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The <see cref="IEnumerator"/>.
|
||||
/// </returns>
|
||||
public IEnumerator<IPublishedContent> GetEnumerator()
|
||||
{
|
||||
return _items.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The get enumerator.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The <see cref="IEnumerator"/>.
|
||||
/// </returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
|
||||
[TypeConverter(typeof(PublishedContentTypeConverter))]
|
||||
public class PublishedContentExtended : PublishedContentWrapped, IPublishedContentExtended
|
||||
{
|
||||
#region Constructor
|
||||
@@ -186,6 +187,11 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return Id.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -179,7 +179,7 @@ namespace Umbraco.Core.Models.PublishedContent
|
||||
}
|
||||
|
||||
if (contentType == null)
|
||||
throw new Exception(string.Format("ContentTypeService failed to find a {0} type with alias \"{1}\".",
|
||||
throw new InvalidOperationException(string.Format("ContentTypeService failed to find a {0} type with alias \"{1}\".",
|
||||
itemType.ToString().ToLower(), alias));
|
||||
|
||||
return new PublishedContentType(contentType);
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
|
||||
namespace Umbraco.Core.Models.PublishedContent
|
||||
{
|
||||
internal class PublishedContentTypeConverter : TypeConverter
|
||||
{
|
||||
private static readonly Type[] ConvertableTypes = new[]
|
||||
{
|
||||
typeof(int)
|
||||
};
|
||||
|
||||
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
|
||||
{
|
||||
return ConvertableTypes.Any(x => TypeHelper.IsTypeAssignableFrom(x, destinationType))
|
||||
|| base.CanConvertFrom(context, destinationType);
|
||||
}
|
||||
|
||||
public override object ConvertTo(
|
||||
ITypeDescriptorContext context,
|
||||
CultureInfo culture,
|
||||
object value,
|
||||
Type destinationType)
|
||||
{
|
||||
var publishedContent = value as IPublishedContent;
|
||||
if (publishedContent == null)
|
||||
return null;
|
||||
|
||||
if (TypeHelper.IsTypeAssignableFrom<int>(destinationType))
|
||||
{
|
||||
return publishedContent.Id;
|
||||
}
|
||||
|
||||
return base.ConvertTo(context, culture, value, destinationType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
namespace Umbraco.Core.Models
|
||||
{
|
||||
// <summary>The Range class. Adapted from http://stackoverflow.com/questions/5343006/is-there-a-c-sharp-type-for-representing-an-integer-range</summary>
|
||||
/// <typeparam name="T">Generic parameter.</typeparam>
|
||||
public class Range<T> where T : IComparable<T>
|
||||
{
|
||||
/// <summary>Minimum value of the range.</summary>
|
||||
public T Minimum { get; set; }
|
||||
|
||||
/// <summary>Maximum value of the range.</summary>
|
||||
public T Maximum { get; set; }
|
||||
|
||||
/// <summary>Presents the Range in readable format.</summary>
|
||||
/// <returns>String representation of the Range</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return string.Format("{0},{1}", this.Minimum, this.Maximum);
|
||||
}
|
||||
|
||||
/// <summary>Determines if the range is valid.</summary>
|
||||
/// <returns>True if range is valid, else false</returns>
|
||||
public bool IsValid()
|
||||
{
|
||||
return this.Minimum.CompareTo(this.Maximum) <= 0;
|
||||
}
|
||||
|
||||
/// <summary>Determines if the provided value is inside the range.</summary>
|
||||
/// <param name="value">The value to test</param>
|
||||
/// <returns>True if the value is inside Range, else false</returns>
|
||||
public bool ContainsValue(T value)
|
||||
{
|
||||
return (this.Minimum.CompareTo(value) <= 0) && (value.CompareTo(this.Maximum) <= 0);
|
||||
}
|
||||
|
||||
/// <summary>Determines if this Range is inside the bounds of another range.</summary>
|
||||
/// <param name="Range">The parent range to test on</param>
|
||||
/// <returns>True if range is inclusive, else false</returns>
|
||||
public bool IsInsideRange(Range<T> range)
|
||||
{
|
||||
return this.IsValid() && range.IsValid() && range.ContainsValue(this.Minimum) && range.ContainsValue(this.Maximum);
|
||||
}
|
||||
|
||||
/// <summary>Determines if another range is inside the bounds of this range.</summary>
|
||||
/// <param name="Range">The child range to test</param>
|
||||
/// <returns>True if range is inside, else false</returns>
|
||||
public bool ContainsRange(Range<T> range)
|
||||
{
|
||||
return this.IsValid() && range.IsValid() && this.ContainsValue(range.Minimum) && this.ContainsValue(range.Maximum);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
internal class DataTypeDto
|
||||
{
|
||||
[Column("pk")]
|
||||
[PrimaryKeyColumn(IdentitySeed = 30)]
|
||||
[PrimaryKeyColumn(IdentitySeed = 40)]
|
||||
public int PrimaryKey { get; set; }
|
||||
|
||||
[Column("nodeId")]
|
||||
|
||||
@@ -19,5 +19,8 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
|
||||
[Column("newest")]
|
||||
public bool Newest { get; set; }
|
||||
|
||||
[Column("updateDate")]
|
||||
public DateTime VersionDate { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -10,7 +10,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
[ExplicitColumns]
|
||||
internal class NodeDto
|
||||
{
|
||||
public const int NodeIdSeed = 1050;
|
||||
public const int NodeIdSeed = 1060;
|
||||
|
||||
[Column("id")]
|
||||
[PrimaryKeyColumn(Name = "PK_structure", IdentitySeed = NodeIdSeed)]
|
||||
|
||||
@@ -22,6 +22,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
private readonly string _httpContextKey;
|
||||
private readonly List<Type> _instanceTypes = new List<Type>();
|
||||
private IEnumerable<TResolved> _sortedValues;
|
||||
private readonly Func<HttpContextBase> _httpContextGetter;
|
||||
|
||||
private int _defaultPluginWeight = 100;
|
||||
|
||||
@@ -42,12 +43,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
if (logger == null) throw new ArgumentNullException("logger");
|
||||
CanResolveBeforeFrozen = false;
|
||||
if (scope == ObjectLifetimeScope.HttpRequest)
|
||||
{
|
||||
if (HttpContext.Current == null)
|
||||
throw new InvalidOperationException("Use alternative constructor accepting a HttpContextBase object in order to set the lifetime scope to HttpRequest when HttpContext.Current is null");
|
||||
|
||||
CurrentHttpContext = new HttpContextWrapper(HttpContext.Current);
|
||||
}
|
||||
_httpContextGetter = () => new HttpContextWrapper(HttpContext.Current);
|
||||
|
||||
ServiceProvider = serviceProvider;
|
||||
Logger = logger;
|
||||
@@ -84,7 +80,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
LifetimeScope = ObjectLifetimeScope.HttpRequest;
|
||||
_httpContextKey = GetType().FullName;
|
||||
ServiceProvider = serviceProvider;
|
||||
CurrentHttpContext = httpContext;
|
||||
_httpContextGetter = () => httpContext;
|
||||
_instanceTypes = new List<Type>();
|
||||
|
||||
InitializeAppInstances();
|
||||
@@ -160,7 +156,16 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Gets or sets the <see cref="HttpContextBase"/> used to initialize this object, if any.
|
||||
/// </summary>
|
||||
/// <remarks>If not null, then <c>LifetimeScope</c> will be <c>ObjectLifetimeScope.HttpRequest</c>.</remarks>
|
||||
protected HttpContextBase CurrentHttpContext { get; private set; }
|
||||
protected HttpContextBase CurrentHttpContext
|
||||
{
|
||||
get
|
||||
{
|
||||
var context = _httpContextGetter == null ? null : _httpContextGetter();
|
||||
if (context == null)
|
||||
throw new InvalidOperationException("Cannot use this resolver with lifetime 'HttpRequest' when there is no current HttpContext. Either use the ctor accepting an HttpContextBase, or use the resolver from within a request exclusively.");
|
||||
return context;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the service provider used to instantiate objects
|
||||
@@ -196,7 +201,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// <summary>
|
||||
/// Gets or sets the default type weight.
|
||||
/// </summary>
|
||||
/// <remarks>Determines the weight of types that do not have a <c>WeightAttribute</c> set on
|
||||
/// <remarks>Determines the weight of types that do not have a <c>WeightAttribute</c> set on
|
||||
/// them, when calling <c>GetSortedValues</c>.</remarks>
|
||||
protected virtual int DefaultPluginWeight
|
||||
{
|
||||
@@ -276,7 +281,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Removes a type.
|
||||
/// </summary>
|
||||
/// <param name="value">The type to remove.</param>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
||||
/// the type is not a valid type for the resolver.</exception>
|
||||
public virtual void RemoveType(Type value)
|
||||
{
|
||||
@@ -296,7 +301,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Removes a type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to remove.</typeparam>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support removing types, or
|
||||
/// the type is not a valid type for the resolver.</exception>
|
||||
public void RemoveType<T>()
|
||||
where T : TResolved
|
||||
@@ -309,7 +314,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <param name="types">The types to add.</param>
|
||||
/// <remarks>The types are appended at the end of the list.</remarks>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// a type is not a valid type for the resolver, or a type is already in the collection of types.</exception>
|
||||
protected void AddTypes(IEnumerable<Type> types)
|
||||
{
|
||||
@@ -336,7 +341,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <param name="value">The type to add.</param>
|
||||
/// <remarks>The type is appended at the end of the list.</remarks>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||
public virtual void AddType(Type value)
|
||||
{
|
||||
@@ -362,7 +367,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type to add.</typeparam>
|
||||
/// <remarks>The type is appended at the end of the list.</remarks>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support adding types, or
|
||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||
public void AddType<T>()
|
||||
where T : TResolved
|
||||
@@ -404,7 +409,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <param name="index">The zero-based index at which the type should be inserted.</param>
|
||||
/// <param name="value">The type to insert.</param>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="index"/> is out of range.</exception>
|
||||
public virtual void InsertType(int index, Type value)
|
||||
@@ -430,7 +435,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// Inserts a type at the beginning of the list.
|
||||
/// </summary>
|
||||
/// <param name="value">The type to insert.</param>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// the type is not a valid type for the resolver, or the type is already in the collection of types.</exception>
|
||||
public virtual void InsertType(Type value)
|
||||
{
|
||||
@@ -464,7 +469,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <param name="existingType">The existing type before which to insert.</param>
|
||||
/// <param name="value">The type to insert.</param>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
|
||||
/// or the new type is already in the collection of types.</exception>
|
||||
public virtual void InsertTypeBefore(Type existingType, Type value)
|
||||
@@ -498,7 +503,7 @@ namespace Umbraco.Core.ObjectResolution
|
||||
/// </summary>
|
||||
/// <typeparam name="TExisting">The existing type before which to insert.</typeparam>
|
||||
/// <typeparam name="T">The type to insert.</typeparam>
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// <exception cref="InvalidOperationException">the resolver does not support inserting types, or
|
||||
/// one of the types is not a valid type for the resolver, or the existing type is not in the collection,
|
||||
/// or the new type is already in the collection of types.</exception>
|
||||
public void InsertTypeBefore<TExisting, T>()
|
||||
|
||||
@@ -63,49 +63,6 @@ namespace Umbraco.Core.ObjectResolution
|
||||
}
|
||||
}
|
||||
|
||||
// NOTE - the ugly code below exists only because of umbraco.BusinessLogic.Actions.Action.ReRegisterActionsAndHandlers
|
||||
// which wants to re-register actions and handlers instead of properly restarting the application. Don't even think
|
||||
// about using it for anything else. Also, while the backdoor is open, the resolution system is locked so nothing
|
||||
// can work properly => deadlocks. Therefore, open the backdoor, do resolution changes EXCLUSIVELY, and close the door!
|
||||
|
||||
/// <summary>
|
||||
/// Returns a disposable object that reprents dirty access to temporarily unfrozen resolution configuration.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Should not be used.</para>
|
||||
/// <para>Should be used in a <c>using(Resolution.DirtyBackdoorToConfiguration) { ... }</c> mode.</para>
|
||||
/// <para>Because we just lift the frozen state, and we don't actually re-freeze, the <c>Frozen</c> event does not trigger.</para>
|
||||
/// </remarks>
|
||||
internal static IDisposable DirtyBackdoorToConfiguration
|
||||
{
|
||||
get { return new DirtyBackdoor(); }
|
||||
}
|
||||
|
||||
// keep the class here because it needs write-access to Resolution.IsFrozen
|
||||
private class DirtyBackdoor : IDisposable
|
||||
{
|
||||
|
||||
private readonly IDisposable _lock;
|
||||
private readonly bool _frozen;
|
||||
|
||||
public DirtyBackdoor()
|
||||
{
|
||||
LogHelper.Debug(typeof(DirtyBackdoor), "Creating back door for resolution");
|
||||
|
||||
_lock = new WriteLock(ConfigurationLock);
|
||||
_frozen = _isFrozen;
|
||||
_isFrozen = false;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
LogHelper.Debug(typeof(DirtyBackdoor), "Disposing back door for resolution");
|
||||
|
||||
_isFrozen = _frozen;
|
||||
_lock.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Freezes resolution.
|
||||
/// </summary>
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Umbraco.Core
|
||||
{
|
||||
private readonly bool _keepOldest;
|
||||
|
||||
public OrderedHashSet(bool keepOldest = true)
|
||||
public OrderedHashSet(bool keepOldest = true)
|
||||
{
|
||||
_keepOldest = keepOldest;
|
||||
}
|
||||
|
||||
@@ -72,6 +72,9 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
content.PublishedVersionGuid = publishedDto == null
|
||||
? (dto.DocumentPublishedReadOnlyDto == null ? default(Guid) : dto.DocumentPublishedReadOnlyDto.VersionId)
|
||||
: publishedDto.VersionId;
|
||||
content.PublishedDate = publishedDto == null
|
||||
? (dto.DocumentPublishedReadOnlyDto == null ? default(DateTime) : dto.DocumentPublishedReadOnlyDto.VersionDate)
|
||||
: publishedDto.VersionDate;
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
|
||||
@@ -28,17 +28,17 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
|
||||
#region Implementation of IEntityFactory<IMedia,ContentVersionDto>
|
||||
|
||||
public IMember BuildEntity(MemberDto dto)
|
||||
public static IMember BuildEntity(MemberDto dto, IMemberType contentType)
|
||||
{
|
||||
var member = new Member(
|
||||
dto.ContentVersionDto.ContentDto.NodeDto.Text,
|
||||
dto.Email, dto.LoginName, dto.Password, _contentType);
|
||||
dto.Email, dto.LoginName, dto.Password, contentType);
|
||||
|
||||
try
|
||||
{
|
||||
member.DisableChangeTracking();
|
||||
|
||||
member.Id = _id;
|
||||
member.Id = dto.NodeId;
|
||||
member.Key = dto.ContentVersionDto.ContentDto.NodeDto.UniqueId;
|
||||
member.Path = dto.ContentVersionDto.ContentDto.NodeDto.Path;
|
||||
member.CreatorId = dto.ContentVersionDto.ContentDto.NodeDto.UserId.Value;
|
||||
@@ -62,6 +62,12 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
}
|
||||
}
|
||||
|
||||
[Obsolete("Use the static BuildEntity instead so we don't have to allocate one of these objects everytime we want to map values")]
|
||||
public IMember BuildEntity(MemberDto dto)
|
||||
{
|
||||
return BuildEntity(dto, _contentType);
|
||||
}
|
||||
|
||||
public MemberDto BuildDto(IMember entity)
|
||||
{
|
||||
var dto = new MemberDto
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Reflection;
|
||||
using Umbraco.Core.Models;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Repositories;
|
||||
using Umbraco.Core.Strings;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Factories
|
||||
{
|
||||
@@ -17,7 +18,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
|
||||
//figure out what extra properties we have that are not on the IUmbracoEntity and add them to additional data
|
||||
foreach (var k in originalEntityProperties.Keys
|
||||
.Select(x => new { orig = x, title = x.ConvertCase(StringAliasCaseType.PascalCase) })
|
||||
.Select(x => new { orig = x, title = x.ToCleanString(CleanStringType.PascalCase | CleanStringType.Ascii | CleanStringType.ConvertCase) })
|
||||
.Where(x => entityProps.InvariantContains(x.title) == false))
|
||||
{
|
||||
entity.AdditionalData[k.title] = originalEntityProperties[k.orig];
|
||||
@@ -75,65 +76,6 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
entity.EnableChangeTracking();
|
||||
}
|
||||
}
|
||||
|
||||
public UmbracoEntity BuildEntity(EntityRepository.UmbracoEntityDto dto)
|
||||
{
|
||||
var entity = new UmbracoEntity(dto.Trashed)
|
||||
{
|
||||
CreateDate = dto.CreateDate,
|
||||
CreatorId = dto.UserId.Value,
|
||||
Id = dto.NodeId,
|
||||
Key = dto.UniqueId,
|
||||
Level = dto.Level,
|
||||
Name = dto.Text,
|
||||
NodeObjectTypeId = dto.NodeObjectType.Value,
|
||||
ParentId = dto.ParentId,
|
||||
Path = dto.Path,
|
||||
SortOrder = dto.SortOrder,
|
||||
HasChildren = dto.Children > 0,
|
||||
ContentTypeAlias = dto.Alias ?? string.Empty,
|
||||
ContentTypeIcon = dto.Icon ?? string.Empty,
|
||||
ContentTypeThumbnail = dto.Thumbnail ?? string.Empty,
|
||||
};
|
||||
|
||||
entity.IsPublished = dto.PublishedVersion != default(Guid) || (dto.NewestVersion != default(Guid) && dto.PublishedVersion == dto.NewestVersion);
|
||||
entity.IsDraft = dto.NewestVersion != default(Guid) && (dto.PublishedVersion == default(Guid) || dto.PublishedVersion != dto.NewestVersion);
|
||||
entity.HasPendingChanges = (dto.PublishedVersion != default(Guid) && dto.NewestVersion != default(Guid)) && dto.PublishedVersion != dto.NewestVersion;
|
||||
|
||||
if (dto.UmbracoPropertyDtos != null)
|
||||
{
|
||||
foreach (var propertyDto in dto.UmbracoPropertyDtos)
|
||||
{
|
||||
entity.AdditionalData[propertyDto.PropertyAlias] = new UmbracoEntity.EntityProperty
|
||||
{
|
||||
PropertyEditorAlias = propertyDto.PropertyEditorAlias,
|
||||
Value = propertyDto.NTextValue.IsNullOrWhiteSpace()
|
||||
? propertyDto.NVarcharValue
|
||||
: propertyDto.NTextValue.ConvertToJsonIfPossible()
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
public EntityRepository.UmbracoEntityDto BuildDto(UmbracoEntity entity)
|
||||
{
|
||||
var node = new EntityRepository.UmbracoEntityDto
|
||||
{
|
||||
CreateDate = entity.CreateDate,
|
||||
Level = short.Parse(entity.Level.ToString(CultureInfo.InvariantCulture)),
|
||||
NodeId = entity.Id,
|
||||
NodeObjectType = entity.NodeObjectTypeId,
|
||||
ParentId = entity.ParentId,
|
||||
Path = entity.Path,
|
||||
SortOrder = entity.SortOrder,
|
||||
Text = entity.Name,
|
||||
Trashed = entity.Trashed,
|
||||
UniqueId = entity.Key,
|
||||
UserId = entity.CreatorId
|
||||
};
|
||||
return node;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,12 @@
|
||||
using System.Collections.Concurrent;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using umbraco.interfaces;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Mappers
|
||||
{
|
||||
public abstract class BaseMapper
|
||||
public abstract class BaseMapper : IDiscoverable
|
||||
{
|
||||
private readonly ISqlSyntaxProvider _sqlSyntax;
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
/// </summary>
|
||||
/// <param name="type"></param>
|
||||
/// <returns></returns>
|
||||
internal BaseMapper ResolveMapperByType(Type type)
|
||||
public virtual BaseMapper ResolveMapperByType(Type type)
|
||||
{
|
||||
return _mapperCache.GetOrAdd(type, type1 =>
|
||||
{
|
||||
@@ -67,7 +67,7 @@ namespace Umbraco.Core.Persistence.Mappers
|
||||
return Attempt<BaseMapper>.Succeed(mapper);
|
||||
}
|
||||
|
||||
internal string GetMapping(Type type, string propertyName)
|
||||
public virtual string GetMapping(Type type, string propertyName)
|
||||
{
|
||||
var mapper = ResolveMapperByType(type);
|
||||
var result = mapper.Map(propertyName);
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
namespace Umbraco.Core.Persistence.Migrations
|
||||
using umbraco.interfaces;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations
|
||||
{
|
||||
/// <summary>
|
||||
/// Marker interface for database migrations
|
||||
/// </summary>
|
||||
public interface IMigration
|
||||
public interface IMigration : IDiscoverable
|
||||
{
|
||||
void Up();
|
||||
void Down();
|
||||
|
||||
@@ -130,8 +130,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = Constants.System.DefaultMembersListViewDataTypeId, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,-97", SortOrder = 2, UniqueId = new Guid("AA2C52A0-CE87-4E65-A47C-7DF09358585D"), Text = Constants.Conventions.DataTypes.ListViewPrefix + "Members", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1031, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1031", SortOrder = 2, UniqueId = new Guid("f38bd2d7-65d0-48e6-95dc-87ce06ec2d3d"), Text = Constants.Conventions.MediaTypes.Folder, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1032, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1032", SortOrder = 2, UniqueId = new Guid("cc07b313-0843-4aa8-bbda-871c8da728c8"), Text = Constants.Conventions.MediaTypes.Image, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1033, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1033", SortOrder = 2, UniqueId = new Guid("4c52d8ab-54e6-40cd-999c-7a5f24903e4d"), Text = Constants.Conventions.MediaTypes.File, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1040, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1040", SortOrder = 2, UniqueId = new Guid("21e798da-e06e-4eda-a511-ed257f78d4fa"), Text = "Related Links", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1033, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1033", SortOrder = 2, UniqueId = new Guid("4c52d8ab-54e6-40cd-999c-7a5f24903e4d"), Text = Constants.Conventions.MediaTypes.File, NodeObjectType = new Guid(Constants.ObjectTypes.MediaType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1041, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1041", SortOrder = 2, UniqueId = new Guid("b6b73142-b9c1-4bf8-a16d-e1c23320b549"), Text = "Tags", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1043, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1043", SortOrder = 2, UniqueId = new Guid("1df9f033-e6d4-451f-b8d2-e0cbc50a836f"), Text = "Image Cropper", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1044, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1044", SortOrder = 0, UniqueId = new Guid("d59be02f-1df9-4228-aa1e-01917d806cda"), Text = Constants.Conventions.MemberTypes.DefaultAlias, NodeObjectType = new Guid(Constants.ObjectTypes.MemberType), CreateDate = DateTime.Now });
|
||||
@@ -141,6 +140,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1047, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1047", SortOrder = 2, UniqueId = new Guid("1EA2E01F-EBD8-4CE1-8D71-6B1149E63548"), Text = "Member Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1048, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1048", SortOrder = 2, UniqueId = new Guid("135D60E0-64D9-49ED-AB08-893C9BA44AE5"), Text = "Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1049, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1049", SortOrder = 2, UniqueId = new Guid("9DBBCBBB-2327-434A-B355-AF1B84E5010A"), Text = "Multiple Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1050, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1050", SortOrder = 2, UniqueId = new Guid("B4E3535A-1753-47E2-8568-602CF8CFEE6F"), Text = "Related Links", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
|
||||
//TODO: We're not creating these for 7.0
|
||||
//_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1039, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1039", SortOrder = 2, UniqueId = new Guid("06f349a9-c949-4b6a-8660-59c10451af42"), Text = "Ultimate Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
@@ -246,8 +246,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 12, DataTypeId = -40, PropertyEditorAlias = Constants.PropertyEditors.RadioButtonListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 13, DataTypeId = -41, PropertyEditorAlias = Constants.PropertyEditors.DateAlias, DbType = "Date" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 14, DataTypeId = -42, PropertyEditorAlias = Constants.PropertyEditors.DropDownListAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, PropertyEditorAlias = Constants.PropertyEditors.CheckBoxListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 21, DataTypeId = 1040, PropertyEditorAlias = Constants.PropertyEditors.RelatedLinksAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 15, DataTypeId = -43, PropertyEditorAlias = Constants.PropertyEditors.CheckBoxListAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 22, DataTypeId = 1041, PropertyEditorAlias = Constants.PropertyEditors.TagsAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 24, DataTypeId = 1043, PropertyEditorAlias = Constants.PropertyEditors.ImageCropperAlias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -26, DataTypeId = Constants.System.DefaultContentListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
@@ -259,6 +258,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 27, DataTypeId = 1047, PropertyEditorAlias = Constants.PropertyEditors.MemberPicker2Alias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 28, DataTypeId = 1048, PropertyEditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 29, DataTypeId = 1049, PropertyEditorAlias = Constants.PropertyEditors.MediaPicker2Alias, DbType = "Ntext" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 30, DataTypeId = 1050, PropertyEditorAlias = Constants.PropertyEditors.RelatedLinks2Alias, DbType = "Ntext" });
|
||||
|
||||
//TODO: We're not creating these for 7.0
|
||||
//_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 19, DataTypeId = 1038, PropertyEditorAlias = Constants.PropertyEditors.MarkdownEditorAlias, DbType = "Ntext" });
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Umbraco.Core.Persistence.Migrations
|
||||
Logger = logger;
|
||||
}
|
||||
|
||||
public IMigrationContext Context { get; internal set; }
|
||||
public IMigrationContext Context;
|
||||
|
||||
public abstract void Up();
|
||||
public abstract void Down();
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user