Compare commits
690 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bec4e442fb | |||
| 72cc5ce88b | |||
| 63763d025e | |||
| f76fa6bde6 | |||
| a231cedd8e | |||
| 20526b40bf | |||
| 5008a2be7f | |||
| 03a395d1f9 | |||
| 734df8685d | |||
| 92dad1af1c | |||
| d897e78b27 | |||
| d79115fcdf | |||
| 992073ab4e | |||
| 3c9b144927 | |||
| b7e4f58503 | |||
| c11dce7b6e | |||
| 004a3e2808 | |||
| d05bfc8983 | |||
| 5bb7223a79 | |||
| c9a816f25e | |||
| 334fcf38ec | |||
| 8873d0f79d | |||
| b499b45a5c | |||
| d5a71ec1da | |||
| 1402494e47 | |||
| 7c491c1fc1 | |||
| 460dd69884 | |||
| beda99963e | |||
| b06f16f5f7 | |||
| f9d79871b4 | |||
| 777b02b84c | |||
| e322ab6f75 | |||
| d19bebc404 | |||
| 46dd86c745 | |||
| 62af834176 | |||
| 2dac1b3cf5 | |||
| 68fb951283 | |||
| 1ca825de62 | |||
| 54b57f7d51 | |||
| 2f6e161120 | |||
| 379bbe5bc4 | |||
| 5c558b0eeb | |||
| 298e56ad05 | |||
| d74d2cd945 | |||
| e2dc4f36ad | |||
| 9620c902cc | |||
| abda579da6 | |||
| 2e43e97ae2 | |||
| c7ac3e7691 | |||
| a209a2067c | |||
| 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 | |||
| 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 | |||
| 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 | |||
| a3f6fb78f5 | |||
| 736b3565d0 | |||
| ed782998ef | |||
| 31d980b0c5 | |||
| 9f6e4d4fd5 | |||
| d90658d814 | |||
| 7fa8f04b11 | |||
| bf2232258e | |||
| 8a133938e6 | |||
| c1b3f1977d | |||
| f086156d48 | |||
| 7080013dd6 | |||
| 5bbb44479f | |||
| 5218d31f23 | |||
| 9e55f5835c | |||
| b080825bb2 | |||
| 8bb696bf9a | |||
| 55e8451513 | |||
| 7e4e2a1d5d | |||
| 1101fc199f | |||
| 5027757760 | |||
| d4d040d9ec | |||
| 4f1b76f5ff | |||
| 3b3eda5bfc | |||
| 6de76571d7 | |||
| 0f535f233e | |||
| 56da13fa79 | |||
| 79d4956b75 | |||
| becc07c2bd | |||
| 05fa58694e | |||
| ecc8575454 | |||
| 9acfd8f5d2 | |||
| 0b530ce181 | |||
| 402835d72d | |||
| 08d579ec87 | |||
| 8b92755487 | |||
| 01b48107f3 | |||
| a546803970 | |||
| 96c28c2611 | |||
| 65a22417f7 | |||
| 6c271e7af9 | |||
| df93dfe63c | |||
| 711981adab | |||
| 199c5a9606 | |||
| 5841377431 | |||
| 54efe86020 | |||
| 589704437f | |||
| 9a99ad1416 | |||
| a4077df5b7 | |||
| 5d298e4313 | |||
| 46ef9146c4 | |||
| 3c75693e20 | |||
| b67286f40d | |||
| 32ad98cde2 | |||
| dabeaa26e6 | |||
| 6c3f1c0e32 | |||
| f4b1df1ede | |||
| a85cafe7ab | |||
| 13cf9f46e7 | |||
| d062b51326 | |||
| 41d91ae791 | |||
| dca5a26fe4 | |||
| 7e8f6d391f | |||
| 7aa00ee6e0 | |||
| 2e027e6195 | |||
| a9c5877e5b | |||
| 337ba4ef34 | |||
| 5d69ec2391 | |||
| 9f9b4d2e84 | |||
| 2b0f2577b5 | |||
| c2aa137293 | |||
| 0f32c2d680 | |||
| 555e0a2281 | |||
| 091a89b162 | |||
| 0eab0b606c | |||
| 1fe06a0c9e | |||
| 6022c87540 | |||
| 06d7ae3861 | |||
| 3d4f999c07 | |||
| 96a18ec8e9 | |||
| 65c39a3117 | |||
| 3b7a83ab14 | |||
| 796d665913 | |||
| 458e890c08 | |||
| e32604183c | |||
| 099b05dbbc | |||
| 15150f9a16 | |||
| 259879c964 | |||
| ed87789abe | |||
| 4cf7ae4b4d | |||
| 757b720a68 | |||
| c8968edd65 | |||
| 58b4201eeb | |||
| a39557a3a7 | |||
| 46eda4a3c3 | |||
| 89ebad2fbc | |||
| 815a288bcb | |||
| 67bcd517bf | |||
| 915503fb51 | |||
| ddefdf2627 | |||
| 09492fa779 | |||
| 8122c0b352 | |||
| 28f0ab1001 | |||
| 266f82b6c5 | |||
| 813a8956d3 | |||
| 2239316889 | |||
| 2289938486 | |||
| 2b8db9d1b5 | |||
| 14c903f6a3 | |||
| b8a50b8da3 | |||
| 09300bba71 | |||
| f716479d01 | |||
| fa5044b011 | |||
| 0aefbc045d | |||
| 09788f1ab4 | |||
| 3a58cb35f8 | |||
| 8f47722d7d | |||
| ebed7c40ed | |||
| 8c54e65861 | |||
| 157f9f3285 | |||
| f2cefac866 | |||
| cbcbb895ec | |||
| b98e96f758 | |||
| 9b033a3204 | |||
| 235014c8ca | |||
| d04947a2d3 | |||
| 0a8fa2be4d | |||
| 6e347dd32c | |||
| d3582e2296 | |||
| 33c9e2b58d | |||
| 16f8f6036c | |||
| 49ff36155c | |||
| 512de60693 | |||
| a064ef4aa7 | |||
| 2210bc3f79 | |||
| b6bc83ba71 | |||
| 8f43e9450a | |||
| f3242e8d6a | |||
| f9835d3ec5 | |||
| 49bcf413a4 | |||
| bcfea6986c | |||
| 29b297e072 | |||
| 70accfa95a | |||
| b764a47e7e | |||
| fc7cba1da9 | |||
| 883980ab8d | |||
| 23abbdb288 | |||
| 652a7a3655 | |||
| 8f73514c1d | |||
| 304b863b02 | |||
| f0bdb1a2e9 | |||
| 6fb3c91d3f | |||
| b9095629ed | |||
| f1ec692a73 | |||
| 76b696e3bf | |||
| 7cadbb6398 | |||
| 1a2814a964 | |||
| 28d6622269 | |||
| 86971179ee | |||
| 9c4eacf330 | |||
| 251a67d653 | |||
| bf22399aba | |||
| 0b9a3ef68a | |||
| abe92eabba | |||
| 0e76b27a2d | |||
| 1a37d88855 | |||
| f8d6c7e7d0 | |||
| 90ba9a1a3a | |||
| 6815731da1 | |||
| 2d5ffabe1e | |||
| f61b7579a2 | |||
| 86a3780c61 | |||
| 4d24e7bef8 | |||
| 8d5f7af780 | |||
| 08c8b84a10 | |||
| 552909fde2 | |||
| 7adae4d345 | |||
| 52dce66598 | |||
| d747cf69c3 | |||
| 255fec84bd | |||
| bc5e3b4d66 | |||
| febeb82d10 | |||
| 9142314d39 | |||
| 1c2b2c1409 | |||
| b4eb9f333e | |||
| af00a421cd | |||
| 27164093ea | |||
| 67312d03d0 | |||
| fed06c88e8 | |||
| 5dec2861d9 | |||
| 23b3bb37ee | |||
| 4dabb606e7 | |||
| d5f66ebe02 | |||
| ad9ae867c0 | |||
| c7783d1cd1 | |||
| 2104b109f2 | |||
| 578ca7d41d | |||
| bd38dde1fc | |||
| 42c23da9f5 | |||
| cab1536a30 | |||
| bbd9e4f0fd | |||
| bf9a408c50 | |||
| 33d35fd9f7 | |||
| cc885c1231 | |||
| af287c387e | |||
| acf10eeef0 | |||
| 422dd1a627 | |||
| 759e444624 | |||
| 2a7ef5de26 | |||
| 43e892563d | |||
| 4d1e64b279 | |||
| 975c97cfb0 | |||
| 0c613347ae | |||
| 83f75fdaff | |||
| 487792920b | |||
| 6ae06ad2e0 | |||
| 8387c435d4 | |||
| 5807bbccc4 | |||
| 1bfc041bbe | |||
| a5ca058cb2 | |||
| 88a1ad04aa | |||
| e619c402b4 | |||
| c9294e5281 | |||
| f5a204d1de | |||
| 7c049b55a8 | |||
| 051b3f2e6a | |||
| 21f947efbd | |||
| a68f4e284a | |||
| 90b43584d2 | |||
| 9461e35028 | |||
| d554417fde | |||
| eedcfc122b | |||
| 8cf3110708 | |||
| dbe489c0f2 | |||
| 2652a583e0 | |||
| bc1758f569 | |||
| a898c2d697 | |||
| e612bcae58 | |||
| 9c5526f281 | |||
| 9c803cc234 | |||
| f24fd42a69 | |||
| 9b7f459c44 | |||
| 273a5cef28 | |||
| 7da7c1e5a1 | |||
| a20cc60c10 | |||
| 846ac573cc | |||
| 122295c89f | |||
| 0e727f91da | |||
| 179523224a | |||
| 19e4bee34e | |||
| f1709f6066 | |||
| f2be235f85 | |||
| d97cc36c53 | |||
| db86f6e1ee | |||
| a03e0dfb53 | |||
| ff6ea0b42e | |||
| 384a31e3c6 | |||
| 69b913c608 | |||
| 83757c60b5 | |||
| e95cb14d48 | |||
| 8d598cd37c | |||
| 30c2f95844 | |||
| 0078a5d8cc | |||
| 09085e3bcf | |||
| a31b03b3e2 | |||
| 9ef53536bf | |||
| 547351a719 | |||
| 371c4ae1a3 | |||
| 060137c798 | |||
| a5af5ba1a9 | |||
| 44b90bd4f3 | |||
| 3e558af18f | |||
| 3774d4fc62 | |||
| a24acdb8ce | |||
| f91d5b53c1 | |||
| c053adc9b2 | |||
| e3bc588164 | |||
| 392319d26c | |||
| 584638977c | |||
| be8632db1c | |||
| 094514b91a | |||
| 3c43f4f3c5 | |||
| 12f9392db9 | |||
| d787cb6ad9 | |||
| db02c3b73c | |||
| a10214d82b | |||
| bc61054931 | |||
| 0becdccb68 | |||
| cee92518ea | |||
| a34a8e180d | |||
| f9f48753de | |||
| c9af13df78 | |||
| f66b456d7c | |||
| ca1f43d048 | |||
| e962a48138 | |||
| 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
|
||||
@@ -14,33 +14,33 @@
|
||||
<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)" />
|
||||
<dependency id="MiniProfiler" version="[2.1.0, 3.0.0)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.4.9, 2.0.0)" />
|
||||
<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="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="[2.0.4, 3.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="Markdown" version="[1.14.7, 2.0.0)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.7.0, 5.0.0)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
<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)" />
|
||||
</dependencies>
|
||||
|
||||
@@ -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,8 @@
|
||||
<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" />
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
@@ -337,7 +339,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 +351,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 +385,10 @@
|
||||
<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>
|
||||
</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,3 @@
|
||||
# Usage: on line 2 put the release version, on line 3 put the version comment (example: beta)
|
||||
7.6.0
|
||||
alpha063
|
||||
RC1
|
||||
@@ -10,7 +10,7 @@
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>SQLCE4Umbraco</RootNamespace>
|
||||
<AssemblyName>SQLCE4Umbraco</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SccProjectName>
|
||||
</SccProjectName>
|
||||
@@ -49,9 +49,11 @@
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Data.SqlServerCe, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Data.SqlServerCe.Entity, Version=4.0.0.1, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SqlServerCE.4.0.0.1\lib\System.Data.SqlServerCe.Entity.dll</HintPath>
|
||||
<Private>True</Private>
|
||||
</Reference>
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
|
||||
@@ -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.6.2" /></startup></configuration>
|
||||
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /></startup></configuration>
|
||||
|
||||
+1
-1
@@ -12,4 +12,4 @@ using System.Resources;
|
||||
[assembly: AssemblyVersion("1.0.*")]
|
||||
|
||||
[assembly: AssemblyFileVersion("7.6.0")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0-alpha063")]
|
||||
[assembly: AssemblyInformationalVersion("7.6.0-RC1")]
|
||||
@@ -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,15 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
|
||||
internal class UmbracoUdiTypeAttribute : Attribute
|
||||
{
|
||||
public string UdiType { get; private set; }
|
||||
|
||||
public UmbracoUdiTypeAttribute(string udiType)
|
||||
{
|
||||
UdiType = udiType;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
internal enum ContentXmlStorage
|
||||
{
|
||||
Default,
|
||||
AspNetTemp,
|
||||
EnvironmentTemp
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
internal static class CoreDebugExtensions
|
||||
{
|
||||
private static CoreDebug _coreDebug;
|
||||
|
||||
public static CoreDebug CoreDebug(this UmbracoConfig config)
|
||||
{
|
||||
return _coreDebug ?? (_coreDebug = new CoreDebug());
|
||||
}
|
||||
}
|
||||
|
||||
internal class CoreDebug
|
||||
{
|
||||
public CoreDebug()
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -159,6 +159,12 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return GetOptionalTextElement("defaultDocumentTypeProperty", "Textstring"); }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("showDeprecatedPropertyEditors")]
|
||||
internal InnerTextConfigurationElement<bool> ShowDeprecatedPropertyEditors
|
||||
{
|
||||
get { return GetOptionalTextElement("showDeprecatedPropertyEditors", false); }
|
||||
}
|
||||
|
||||
[ConfigurationProperty("EnableInheritedDocumentTypes")]
|
||||
internal InnerTextConfigurationElement<bool> EnableInheritedDocumentTypes
|
||||
{
|
||||
@@ -171,6 +177,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; }
|
||||
@@ -306,6 +324,11 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
get { return DefaultDocumentTypeProperty; }
|
||||
}
|
||||
|
||||
bool IContentSection.ShowDeprecatedPropertyEditors
|
||||
{
|
||||
get { return ShowDeprecatedPropertyEditors; }
|
||||
}
|
||||
|
||||
bool IContentSection.EnableInheritedDocumentTypes
|
||||
{
|
||||
get { return EnableInheritedDocumentTypes; }
|
||||
@@ -315,5 +338,14 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
{
|
||||
get { return EnableInheritedMediaTypes; }
|
||||
}
|
||||
bool IContentSection.EnablePropertyValueConverters
|
||||
{
|
||||
get { return EnablePropertyValueConverters; }
|
||||
}
|
||||
|
||||
string IContentSection.LoginBackgroundImage
|
||||
{
|
||||
get { return LoginBackgroundImage; }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -60,8 +60,18 @@ namespace Umbraco.Core.Configuration.UmbracoSettings
|
||||
|
||||
string DefaultDocumentTypeProperty { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The default for this is false but if you would like deprecated property editors displayed
|
||||
/// in the data type editor you can enable this
|
||||
/// </summary>
|
||||
bool ShowDeprecatedPropertyEditors { get; }
|
||||
|
||||
bool EnableInheritedDocumentTypes { get; }
|
||||
|
||||
bool EnableInheritedMediaTypes { get; }
|
||||
|
||||
bool EnablePropertyValueConverters { get; }
|
||||
|
||||
string LoginBackgroundImage { get; }
|
||||
}
|
||||
}
|
||||
@@ -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 "alpha063"; } }
|
||||
public static string CurrentComment { get { return "RC1"; } }
|
||||
|
||||
// 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>
|
||||
@@ -109,11 +114,21 @@ namespace Umbraco.Core
|
||||
/// </summary>
|
||||
public const string Member = "39EB0F98-B348-42A1-8662-E7EB18487560";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Media Type object.
|
||||
/// </summary>
|
||||
public static readonly Guid MemberGuid = new Guid(Member);
|
||||
|
||||
/// <summary>
|
||||
/// Guid for a Member Group object.
|
||||
/// </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>
|
||||
@@ -143,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>
|
||||
|
||||
@@ -42,10 +42,14 @@ namespace Umbraco.Core
|
||||
[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 ContentPicker = "158AA029-24ED-4948-939E-C3DA209E5FBA";
|
||||
|
||||
|
||||
[Obsolete("This is an obsoleted content picker, use ContentPicker2Alias instead")]
|
||||
public const string ContentPickerAlias = "Umbraco.ContentPickerAlias";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the Content Picker datatype.
|
||||
/// </summary>
|
||||
public const string ContentPickerAlias = "Umbraco.ContentPickerAlias";
|
||||
public const string ContentPicker2Alias = "Umbraco.ContentPicker2";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the Date datatype.
|
||||
@@ -192,11 +196,15 @@ namespace Umbraco.Core
|
||||
[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 MediaPicker = "EAD69342-F06D-4253-83AC-28000225583B";
|
||||
|
||||
[Obsolete("This is an obsoleted picker, use MediaPicker2Alias instead")]
|
||||
public const string MediaPickerAlias = "Umbraco.MediaPicker";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the Media Picker datatype.
|
||||
/// </summary>
|
||||
public const string MediaPickerAlias = "Umbraco.MediaPicker";
|
||||
public const string MediaPicker2Alias = "Umbraco.MediaPicker2";
|
||||
|
||||
[Obsolete("This is an obsoleted picker, use MediaPicker2Alias instead")]
|
||||
public const string MultipleMediaPickerAlias = "Umbraco.MultipleMediaPicker";
|
||||
|
||||
/// <summary>
|
||||
@@ -205,26 +213,32 @@ namespace Umbraco.Core
|
||||
[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 MemberPicker = "39F533E4-0551-4505-A64B-E0425C5CE775";
|
||||
|
||||
[Obsolete("This is an obsoleted picker, use MemberPicker2Alias instead")]
|
||||
public const string MemberPickerAlias = "Umbraco.MemberPicker";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the Member Picker datatype.
|
||||
/// </summary>
|
||||
public const string MemberPickerAlias = "Umbraco.MemberPicker";
|
||||
public const string MemberPicker2Alias = "Umbraco.MemberPicker2";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the Member Group Picker datatype.
|
||||
/// </summary>
|
||||
public const string MemberGroupPickerAlias = "Umbraco.MemberGroupPicker";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the Multi-Node Tree Picker datatype
|
||||
/// </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 MultiNodeTreePicker = "7E062C13-7C41-4AD9-B389-41D88AEEF87C";
|
||||
|
||||
[Obsolete("This is an obsoleted picker, use MultiNodeTreePicker2Alias instead")]
|
||||
public const string MultiNodeTreePickerAlias = "Umbraco.MultiNodeTreePicker";
|
||||
|
||||
/// <summary>
|
||||
/// Alias for the Multi-Node Tree Picker datatype
|
||||
/// </summary>
|
||||
public const string MultiNodeTreePickerAlias = "Umbraco.MultiNodeTreePicker";
|
||||
public const string MultiNodeTreePicker2Alias = "Umbraco.MultiNodeTreePicker2";
|
||||
|
||||
/// <summary>
|
||||
/// Guid for the Multiple Textstring datatype.
|
||||
@@ -275,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>
|
||||
|
||||
@@ -16,6 +16,7 @@ namespace Umbraco.Core.Deploy
|
||||
if (udi == null)
|
||||
throw new ArgumentNullException("udi");
|
||||
Udi = udi;
|
||||
Name = Udi.ToString();
|
||||
|
||||
Dependencies = dependencies ?? Enumerable.Empty<ArtifactDependency>();
|
||||
_checksum = new Lazy<string>(GetChecksum);
|
||||
@@ -48,5 +49,8 @@ namespace Umbraco.Core.Deploy
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public string Name { get; set; }
|
||||
public string Alias { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -4,5 +4,8 @@ namespace Umbraco.Core.Deploy
|
||||
/// Represents an artifact ie an object that can be transfered between environments.
|
||||
/// </summary>
|
||||
public interface IArtifact : IArtifactSignature
|
||||
{ }
|
||||
{
|
||||
string Name { get; }
|
||||
string Alias { get; }
|
||||
}
|
||||
}
|
||||
@@ -66,10 +66,20 @@ namespace Umbraco.Core.Deploy
|
||||
/// <returns>The length of the file, or -1 if the file does not exist.</returns>
|
||||
Task<long> GetFileLengthAsync(StringUdi udi, CancellationToken token);
|
||||
|
||||
// fixme - doc
|
||||
void GetFiles(IEnumerable<StringUdi> udis, IFileStore fileStore);
|
||||
/// <summary>
|
||||
/// Gets files and store them using a file store.
|
||||
/// </summary>
|
||||
/// <param name="udis">The udis of the files to get.</param>
|
||||
/// <param name="fileTypes">A collection of file types which can store the files.</param>
|
||||
void GetFiles(IEnumerable<StringUdi> udis, IFileTypeCollection fileTypes);
|
||||
|
||||
Task GetFilesAsync(IEnumerable<StringUdi> udis, IFileStore fileStore, CancellationToken token);
|
||||
/// <summary>
|
||||
/// Gets files and store them using a file store.
|
||||
/// </summary>
|
||||
/// <param name="udis">The udis of the files to get.</param>
|
||||
/// <param name="fileTypes">A collection of file types which can store the files.</param>
|
||||
/// <param name="token">A cancellation token.</param>
|
||||
Task GetFilesAsync(IEnumerable<StringUdi> udis, IFileTypeCollection fileTypes, CancellationToken token);
|
||||
|
||||
///// <summary>
|
||||
///// Gets the content of a file as a bytes array.
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Umbraco.Core.Deploy
|
||||
{
|
||||
public interface IFileStore
|
||||
{
|
||||
void SaveStream(StringUdi udi, Stream stream);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Core.Deploy
|
||||
{
|
||||
public interface IFileType
|
||||
{
|
||||
Stream GetStream(StringUdi udi);
|
||||
|
||||
Task<Stream> GetStreamAsync(StringUdi udi, CancellationToken token);
|
||||
|
||||
Stream GetChecksumStream(StringUdi udi);
|
||||
|
||||
long GetLength(StringUdi udi);
|
||||
|
||||
void SetStream(StringUdi udi, Stream stream);
|
||||
|
||||
Task SetStreamAsync(StringUdi udi, Stream stream, CancellationToken token);
|
||||
|
||||
bool CanSetPhysical { get; }
|
||||
|
||||
void Set(StringUdi udi, string physicalPath, bool copy = false);
|
||||
|
||||
// this is not pretty as *everywhere* in Deploy we take care of ignoring
|
||||
// the physical path and always rely on Core's virtual IFileSystem but
|
||||
// Cloud wants to add some of these files to Git and needs the path...
|
||||
string GetPhysicalPath(StringUdi udi);
|
||||
|
||||
string GetVirtualPath(StringUdi udi);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Umbraco.Core.Deploy
|
||||
{
|
||||
public interface IFileTypeCollection
|
||||
{
|
||||
IFileType this[string entityType] { get; }
|
||||
|
||||
bool Contains(string entityType);
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
namespace Umbraco.Core.Deploy
|
||||
{
|
||||
public interface IPrettyArtifact
|
||||
{
|
||||
string Name { get; }
|
||||
string Alias { get; }
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
@@ -67,22 +68,15 @@ namespace Umbraco.Core
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The for each.</summary>
|
||||
/// <param name="items">The items.</param>
|
||||
/// <param name="func">The func.</param>
|
||||
/// <typeparam name="TItem">item type</typeparam>
|
||||
/// <typeparam name="TResult">Result type</typeparam>
|
||||
/// <returns>the Results</returns>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use a normal foreach loop instead, this adds more allocations than necessary")]
|
||||
public static TResult[] ForEach<TItem, TResult>(this IEnumerable<TItem> items, Func<TItem, TResult> func)
|
||||
{
|
||||
return items.Select(func).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>The for each.</summary>
|
||||
/// <param name="items">The items.</param>
|
||||
/// <param name="action">The action.</param>
|
||||
/// <typeparam name="TItem">Item type</typeparam>
|
||||
/// <returns>list of TItem</returns>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Use a normal foreach loop instead, this adds more allocations than necessary")]
|
||||
public static IEnumerable<TItem> ForEach<TItem>(this IEnumerable<TItem> items, Action<TItem> action)
|
||||
{
|
||||
if (items != null)
|
||||
@@ -101,6 +95,7 @@ namespace Umbraco.Core
|
||||
/// <param name="f">The select child.</param>
|
||||
/// <typeparam name="T">Item type</typeparam>
|
||||
/// <returns>list of TItem</returns>
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
[Obsolete("Do not use, use SelectRecursive instead which has far less potential of re-iterating an iterator which may cause significantly more SQL queries")]
|
||||
public static IEnumerable<T> FlattenList<T>(this IEnumerable<T> e, Func<T, IEnumerable<T>> f)
|
||||
{
|
||||
@@ -300,6 +295,5 @@ namespace Umbraco.Core
|
||||
return list1Groups.Count == list2Groups.Count
|
||||
&& list1Groups.All(g => g.Count() == list2Groups[g.Key].Count());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,13 +16,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 +39,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
using System;
|
||||
using Umbraco.Core.Scoping;
|
||||
|
||||
namespace Umbraco.Core.Events
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores the instance of EventMessages in the current scope.
|
||||
/// </summary>
|
||||
internal class ScopeLifespanMessagesFactory : IEventMessagesFactory
|
||||
{
|
||||
public const string ContextKey = "Umbraco.Core.Events.ScopeLifespanMessagesFactory";
|
||||
|
||||
private readonly IHttpContextAccessor _contextAccessor;
|
||||
private readonly IScopeProviderInternal _scopeProvider;
|
||||
|
||||
public static ScopeLifespanMessagesFactory Current { get; private set; }
|
||||
|
||||
public ScopeLifespanMessagesFactory(IHttpContextAccessor contextAccesor, IScopeProvider scopeProvider)
|
||||
{
|
||||
if (contextAccesor == null) throw new ArgumentNullException("contextAccesor");
|
||||
if (scopeProvider == null) throw new ArgumentNullException("scopeProvider");
|
||||
if (scopeProvider is IScopeProviderInternal == false) throw new ArgumentException("Not IScopeProviderInternal.", "scopeProvider");
|
||||
_contextAccessor = contextAccesor;
|
||||
_scopeProvider = (IScopeProviderInternal) scopeProvider;
|
||||
Current = this;
|
||||
}
|
||||
|
||||
public EventMessages Get()
|
||||
{
|
||||
var messages = GetFromHttpContext();
|
||||
if (messages != null) return messages;
|
||||
|
||||
var scope = _scopeProvider.GetAmbientOrNoScope();
|
||||
return scope.Messages;
|
||||
}
|
||||
|
||||
public EventMessages GetFromHttpContext()
|
||||
{
|
||||
if (_contextAccessor == null || _contextAccessor.Value == null) return null;
|
||||
return (EventMessages)_contextAccessor.Value.Items[ContextKey];
|
||||
}
|
||||
|
||||
public EventMessages TryGet()
|
||||
{
|
||||
var messages = GetFromHttpContext();
|
||||
if (messages != null) return messages;
|
||||
|
||||
var scope = _scopeProvider.AmbientScope;
|
||||
return scope == null ? null : scope.MessagesOrNull;
|
||||
}
|
||||
|
||||
public void Set(EventMessages messages)
|
||||
{
|
||||
if (_contextAccessor.Value == null) return;
|
||||
_contextAccessor.Value.Items[ContextKey] = messages;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
public interface IHttpContextAccessor
|
||||
{
|
||||
HttpContextBase Value { get; }
|
||||
}
|
||||
}
|
||||
@@ -12,25 +12,18 @@ namespace Umbraco.Core.IO
|
||||
public class FileSystemProviderManager
|
||||
{
|
||||
private readonly FileSystemProvidersSection _config;
|
||||
private readonly WeakSet<ShadowWrapper> _wrappers = new WeakSet<ShadowWrapper>();
|
||||
private readonly ConcurrentSet<ShadowWrapper> _wrappers = new ConcurrentSet<ShadowWrapper>();
|
||||
|
||||
// actual well-known filesystems returned by properties
|
||||
private readonly IFileSystem2 _macroPartialFileSystem;
|
||||
private readonly IFileSystem2 _partialViewsFileSystem;
|
||||
private readonly IFileSystem2 _stylesheetsFileSystem;
|
||||
private readonly IFileSystem2 _scriptsFileSystem;
|
||||
private readonly IFileSystem2 _xsltFileSystem;
|
||||
private readonly IFileSystem2 _masterPagesFileSystem;
|
||||
private readonly IFileSystem2 _mvcViewsFileSystem;
|
||||
private readonly ConcurrentDictionary<string, ProviderConstructionInfo> _providerLookup = new ConcurrentDictionary<string, ProviderConstructionInfo>();
|
||||
private readonly ConcurrentDictionary<string, IFileSystem2> _filesystems = new ConcurrentDictionary<string, IFileSystem2>();
|
||||
|
||||
// when shadowing is enabled, above filesystems, as wrappers
|
||||
private readonly ShadowWrapper _macroPartialFileSystemWrapper;
|
||||
private readonly ShadowWrapper _partialViewsFileSystemWrapper;
|
||||
private readonly ShadowWrapper _stylesheetsFileSystemWrapper;
|
||||
private readonly ShadowWrapper _scriptsFileSystemWrapper;
|
||||
private readonly ShadowWrapper _xsltFileSystemWrapper;
|
||||
private readonly ShadowWrapper _masterPagesFileSystemWrapper;
|
||||
private readonly ShadowWrapper _mvcViewsFileSystemWrapper;
|
||||
private ShadowWrapper _macroPartialFileSystem;
|
||||
private ShadowWrapper _partialViewsFileSystem;
|
||||
private ShadowWrapper _stylesheetsFileSystem;
|
||||
private ShadowWrapper _scriptsFileSystem;
|
||||
private ShadowWrapper _xsltFileSystem;
|
||||
private ShadowWrapper _masterPagesFileSystem;
|
||||
private ShadowWrapper _mvcViewsFileSystem;
|
||||
|
||||
#region Singleton & Constructor
|
||||
|
||||
@@ -41,31 +34,46 @@ namespace Umbraco.Core.IO
|
||||
get { return Instance; }
|
||||
}
|
||||
|
||||
// for tests only, totally unsafe
|
||||
internal void Reset()
|
||||
{
|
||||
_wrappers.Clear();
|
||||
_providerLookup.Clear();
|
||||
_filesystems.Clear();
|
||||
CreateWellKnownFileSystems();
|
||||
}
|
||||
|
||||
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; }
|
||||
}
|
||||
|
||||
internal FileSystemProviderManager()
|
||||
{
|
||||
_config = (FileSystemProvidersSection) ConfigurationManager.GetSection("umbracoConfiguration/FileSystemProviders");
|
||||
CreateWellKnownFileSystems();
|
||||
}
|
||||
|
||||
_macroPartialFileSystem = new PhysicalFileSystem(SystemDirectories.MacroPartials);
|
||||
_partialViewsFileSystem = new PhysicalFileSystem(SystemDirectories.PartialViews);
|
||||
_stylesheetsFileSystem = new PhysicalFileSystem(SystemDirectories.Css);
|
||||
_scriptsFileSystem = new PhysicalFileSystem(SystemDirectories.Scripts);
|
||||
_xsltFileSystem = new PhysicalFileSystem(SystemDirectories.Xslt);
|
||||
_masterPagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages);
|
||||
_mvcViewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews);
|
||||
private void CreateWellKnownFileSystems()
|
||||
{
|
||||
var macroPartialFileSystem = new PhysicalFileSystem(SystemDirectories.MacroPartials);
|
||||
var partialViewsFileSystem = new PhysicalFileSystem(SystemDirectories.PartialViews);
|
||||
var stylesheetsFileSystem = new PhysicalFileSystem(SystemDirectories.Css);
|
||||
var scriptsFileSystem = new PhysicalFileSystem(SystemDirectories.Scripts);
|
||||
var xsltFileSystem = new PhysicalFileSystem(SystemDirectories.Xslt);
|
||||
var masterPagesFileSystem = new PhysicalFileSystem(SystemDirectories.Masterpages);
|
||||
var mvcViewsFileSystem = new PhysicalFileSystem(SystemDirectories.MvcViews);
|
||||
|
||||
_macroPartialFileSystem = _macroPartialFileSystemWrapper = new ShadowWrapper(_macroPartialFileSystem, "Views/MacroPartials", ScopeProvider);
|
||||
_partialViewsFileSystem = _partialViewsFileSystemWrapper = new ShadowWrapper(_partialViewsFileSystem, "Views/Partials", ScopeProvider);
|
||||
_stylesheetsFileSystem = _stylesheetsFileSystemWrapper = new ShadowWrapper(_stylesheetsFileSystem, "css", ScopeProvider);
|
||||
_scriptsFileSystem = _scriptsFileSystemWrapper = new ShadowWrapper(_scriptsFileSystem, "scripts", ScopeProvider);
|
||||
_xsltFileSystem = _xsltFileSystemWrapper = new ShadowWrapper(_xsltFileSystem, "xslt", ScopeProvider);
|
||||
_masterPagesFileSystem = _masterPagesFileSystemWrapper = new ShadowWrapper(_masterPagesFileSystem, "masterpages", ScopeProvider);
|
||||
_mvcViewsFileSystem = _mvcViewsFileSystemWrapper = new ShadowWrapper(_mvcViewsFileSystem, "Views", ScopeProvider);
|
||||
_macroPartialFileSystem = new ShadowWrapper(macroPartialFileSystem, "Views/MacroPartials", ScopeProvider);
|
||||
_partialViewsFileSystem = new ShadowWrapper(partialViewsFileSystem, "Views/Partials", ScopeProvider);
|
||||
_stylesheetsFileSystem = new ShadowWrapper(stylesheetsFileSystem, "css", ScopeProvider);
|
||||
_scriptsFileSystem = new ShadowWrapper(scriptsFileSystem, "scripts", ScopeProvider);
|
||||
_xsltFileSystem = new ShadowWrapper(xsltFileSystem, "xslt", ScopeProvider);
|
||||
_masterPagesFileSystem = new ShadowWrapper(masterPagesFileSystem, "masterpages", ScopeProvider);
|
||||
_mvcViewsFileSystem = new ShadowWrapper(mvcViewsFileSystem, "Views", ScopeProvider);
|
||||
|
||||
// filesystems obtained from GetFileSystemProvider are already wrapped and do not need to be wrapped again
|
||||
MediaFileSystem = GetFileSystemProvider<MediaFileSystem>();
|
||||
@@ -80,7 +88,7 @@ namespace Umbraco.Core.IO
|
||||
public IFileSystem2 StylesheetsFileSystem { get { return _stylesheetsFileSystem; } }
|
||||
public IFileSystem2 ScriptsFileSystem { get { return _scriptsFileSystem; } }
|
||||
public IFileSystem2 XsltFileSystem { get { return _xsltFileSystem; } }
|
||||
public IFileSystem2 MasterPagesFileSystem { get { return _masterPagesFileSystem; } }
|
||||
public IFileSystem2 MasterPagesFileSystem { get { return _mvcViewsFileSystem; } }
|
||||
public IFileSystem2 MvcViewsFileSystem { get { return _mvcViewsFileSystem; } }
|
||||
public MediaFileSystem MediaFileSystem { get; private set; }
|
||||
|
||||
@@ -98,56 +106,74 @@ namespace Umbraco.Core.IO
|
||||
//public string ProviderAlias { get; set; }
|
||||
}
|
||||
|
||||
private readonly ConcurrentDictionary<string, ProviderConstructionInfo> _providerLookup = new ConcurrentDictionary<string, ProviderConstructionInfo>();
|
||||
private readonly ConcurrentDictionary<Type, string> _aliases = new ConcurrentDictionary<Type, string>();
|
||||
|
||||
/// <summary>
|
||||
/// Gets an underlying (non-typed) filesystem supporting a strongly-typed filesystem.
|
||||
/// </summary>
|
||||
/// <param name="alias">The alias of the strongly-typed filesystem.</param>
|
||||
/// <returns>The non-typed filesystem supporting the strongly-typed filesystem with the specified alias.</returns>
|
||||
/// <remarks>This method should not be used directly, used <see cref="GetFileSystemProvider{TFileSystem}"/> instead.</remarks>
|
||||
/// <remarks>This method should not be used directly, used <see cref="GetFileSystemProvider{TFileSystem}()"/> instead.</remarks>
|
||||
public IFileSystem GetUnderlyingFileSystemProvider(string alias)
|
||||
{
|
||||
return GetUnderlyingFileSystemProvider(alias, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets an underlying (non-typed) filesystem supporting a strongly-typed filesystem.
|
||||
/// </summary>
|
||||
/// <param name="alias">The alias of the strongly-typed filesystem.</param>
|
||||
/// /// <param name="fallback">A fallback creator for the filesystem.</param>
|
||||
/// <returns>The non-typed filesystem supporting the strongly-typed filesystem with the specified alias.</returns>
|
||||
/// <remarks>This method should not be used directly, used <see cref="GetFileSystemProvider{TFileSystem}()"/> instead.</remarks>
|
||||
private IFileSystem GetUnderlyingFileSystemProvider(string alias, Func<IFileSystem> fallback)
|
||||
{
|
||||
// either get the constructor info from cache or create it and add to cache
|
||||
var ctorInfo = _providerLookup.GetOrAdd(alias, s =>
|
||||
{
|
||||
// get config
|
||||
var providerConfig = _config.Providers[s];
|
||||
if (providerConfig == null)
|
||||
throw new ArgumentException(string.Format("No provider found with alias {0}.", s));
|
||||
var ctorInfo = _providerLookup.GetOrAdd(alias, _ => GetUnderlyingFileSystemCtor(alias, fallback));
|
||||
return ctorInfo == null ? fallback() : (IFileSystem) ctorInfo.Constructor.Invoke(ctorInfo.Parameters);
|
||||
}
|
||||
|
||||
// get the filesystem type
|
||||
var providerType = Type.GetType(providerConfig.Type);
|
||||
if (providerType == null)
|
||||
throw new InvalidOperationException(string.Format("Could not find type {0}.", providerConfig.Type));
|
||||
private IFileSystem GetUnderlyingFileSystemNoCache(string alias, Func<IFileSystem> fallback)
|
||||
{
|
||||
var ctorInfo = GetUnderlyingFileSystemCtor(alias, fallback);
|
||||
return ctorInfo == null ? fallback() : (IFileSystem) ctorInfo.Constructor.Invoke(ctorInfo.Parameters);
|
||||
}
|
||||
|
||||
// ensure it implements IFileSystem
|
||||
if (providerType.IsAssignableFrom(typeof (IFileSystem)))
|
||||
throw new InvalidOperationException(string.Format("Type {0} does not implement IFileSystem.", providerType.FullName));
|
||||
private ProviderConstructionInfo GetUnderlyingFileSystemCtor(string alias, Func<IFileSystem> fallback)
|
||||
{
|
||||
// get config
|
||||
var providerConfig = _config.Providers[alias];
|
||||
if (providerConfig == null)
|
||||
{
|
||||
if (fallback != null) return null;
|
||||
throw new ArgumentException(string.Format("No provider found with alias {0}.", alias));
|
||||
}
|
||||
|
||||
// find a ctor matching the config parameters
|
||||
var paramCount = providerConfig.Parameters != null ? providerConfig.Parameters.Count : 0;
|
||||
var constructor = providerType.GetConstructors().SingleOrDefault(x
|
||||
=> x.GetParameters().Length == paramCount && x.GetParameters().All(y => providerConfig.Parameters.AllKeys.Contains(y.Name)));
|
||||
if (constructor == null)
|
||||
throw new InvalidOperationException(string.Format("Type {0} has no ctor matching the {1} configuration parameter(s).", providerType.FullName, paramCount));
|
||||
// get the filesystem type
|
||||
var providerType = Type.GetType(providerConfig.Type);
|
||||
if (providerType == null)
|
||||
throw new InvalidOperationException(string.Format("Could not find type {0}.", providerConfig.Type));
|
||||
|
||||
var parameters = new object[paramCount];
|
||||
if (providerConfig.Parameters != null) // keeps ReSharper happy
|
||||
for (var i = 0; i < paramCount; i++)
|
||||
parameters[i] = providerConfig.Parameters[providerConfig.Parameters.AllKeys[i]].Value;
|
||||
// ensure it implements IFileSystem
|
||||
if (providerType.IsAssignableFrom(typeof(IFileSystem)))
|
||||
throw new InvalidOperationException(string.Format("Type {0} does not implement IFileSystem.", providerType.FullName));
|
||||
|
||||
return new ProviderConstructionInfo
|
||||
{
|
||||
Constructor = constructor,
|
||||
Parameters = parameters,
|
||||
//ProviderAlias = s
|
||||
};
|
||||
});
|
||||
// find a ctor matching the config parameters
|
||||
var paramCount = providerConfig.Parameters != null ? providerConfig.Parameters.Count : 0;
|
||||
var constructor = providerType.GetConstructors().SingleOrDefault(x
|
||||
=> x.GetParameters().Length == paramCount && x.GetParameters().All(y => providerConfig.Parameters.AllKeys.Contains(y.Name)));
|
||||
if (constructor == null)
|
||||
throw new InvalidOperationException(string.Format("Type {0} has no ctor matching the {1} configuration parameter(s).", providerType.FullName, paramCount));
|
||||
|
||||
// create the fs and return
|
||||
return (IFileSystem) ctorInfo.Constructor.Invoke(ctorInfo.Parameters);
|
||||
var parameters = new object[paramCount];
|
||||
if (providerConfig.Parameters != null) // keeps ReSharper happy
|
||||
for (var i = 0; i < paramCount; i++)
|
||||
parameters[i] = providerConfig.Parameters[providerConfig.Parameters.AllKeys[i]].Value;
|
||||
|
||||
return new ProviderConstructionInfo
|
||||
{
|
||||
Constructor = constructor,
|
||||
Parameters = parameters,
|
||||
//ProviderAlias = s
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -155,38 +181,68 @@ namespace Umbraco.Core.IO
|
||||
/// </summary>
|
||||
/// <typeparam name="TFileSystem">The type of the filesystem.</typeparam>
|
||||
/// <returns>A strongly-typed filesystem of the specified type.</returns>
|
||||
/// <remarks>
|
||||
/// <para>Ideally, this should cache the instances, but that would break backward compatibility, so we
|
||||
/// only do it for our own MediaFileSystem - for everything else, it's the responsibility of the caller
|
||||
/// to ensure that they maintain singletons. This is important for singletons, as each filesystem maintains
|
||||
/// its own shadow and having multiple instances would lead to inconsistencies.</para>
|
||||
/// <para>Note that any filesystem created by this method *after* shadowing begins, will *not* be
|
||||
/// shadowing (and an exception will be thrown by the ShadowWrapper).</para>
|
||||
/// </remarks>
|
||||
public TFileSystem GetFileSystemProvider<TFileSystem>()
|
||||
where TFileSystem : FileSystemWrapper
|
||||
where TFileSystem : FileSystemWrapper
|
||||
{
|
||||
// deal with known types - avoid infinite loops!
|
||||
if (typeof(TFileSystem) == typeof(MediaFileSystem) && MediaFileSystem != null)
|
||||
return MediaFileSystem as TFileSystem; // else create and return
|
||||
return GetFileSystemProvider<TFileSystem>(null);
|
||||
}
|
||||
|
||||
// get/cache the alias for the filesystem type
|
||||
var alias = _aliases.GetOrAdd(typeof (TFileSystem), fsType =>
|
||||
{
|
||||
// validate the ctor
|
||||
var constructor = fsType.GetConstructors().SingleOrDefault(x
|
||||
=> x.GetParameters().Length == 1 && TypeHelper.IsTypeAssignableFrom<IFileSystem>(x.GetParameters().Single().ParameterType));
|
||||
if (constructor == null)
|
||||
throw new InvalidOperationException("Type " + fsType.FullName + " must inherit from FileSystemWrapper and have a constructor that accepts one parameter of type " + typeof(IFileSystem).FullName + ".");
|
||||
/// <summary>
|
||||
/// Gets a strongly-typed filesystem.
|
||||
/// </summary>
|
||||
/// <typeparam name="TFileSystem">The type of the filesystem.</typeparam>
|
||||
/// <param name="fallback">A fallback creator for the inner filesystem.</param>
|
||||
/// <returns>A strongly-typed filesystem of the specified type.</returns>
|
||||
/// <remarks>
|
||||
/// <para>The fallback creator is used only if nothing is configured.</para>
|
||||
/// <para>Ideally, this should cache the instances, but that would break backward compatibility, so we
|
||||
/// only do it for our own MediaFileSystem - for everything else, it's the responsibility of the caller
|
||||
/// to ensure that they maintain singletons. This is important for singletons, as each filesystem maintains
|
||||
/// its own shadow and having multiple instances would lead to inconsistencies.</para>
|
||||
/// <para>Note that any filesystem created by this method *after* shadowing begins, will *not* be
|
||||
/// shadowing (and an exception will be thrown by the ShadowWrapper).</para>
|
||||
/// </remarks>
|
||||
public TFileSystem GetFileSystemProvider<TFileSystem>(Func<IFileSystem> fallback)
|
||||
where TFileSystem : FileSystemWrapper
|
||||
{
|
||||
var alias = GetFileSystemAlias<TFileSystem>();
|
||||
return (TFileSystem) _filesystems.GetOrAdd(alias, _ =>
|
||||
{
|
||||
// gets the inner fs, create the strongly-typed fs wrapping the inner fs, register & return
|
||||
// so we are double-wrapping here
|
||||
// could be optimized by having FileSystemWrapper inherit from ShadowWrapper, maybe
|
||||
var innerFs = GetUnderlyingFileSystemNoCache(alias, fallback);
|
||||
var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias, ScopeProvider);
|
||||
var fs = (IFileSystem2) Activator.CreateInstance(typeof (TFileSystem), shadowWrapper);
|
||||
_wrappers.Add(shadowWrapper); // keeping a reference to the wrapper
|
||||
return fs;
|
||||
});
|
||||
}
|
||||
|
||||
// find the attribute and get the alias
|
||||
var attr = (FileSystemProviderAttribute) fsType.GetCustomAttributes(typeof(FileSystemProviderAttribute), false).SingleOrDefault();
|
||||
if (attr == null)
|
||||
throw new InvalidOperationException("Type " + fsType.FullName + "is missing the required FileSystemProviderAttribute.");
|
||||
private string GetFileSystemAlias<TFileSystem>()
|
||||
{
|
||||
var fsType = typeof(TFileSystem);
|
||||
|
||||
return attr.Alias;
|
||||
});
|
||||
// validate the ctor
|
||||
var constructor = fsType.GetConstructors().SingleOrDefault(x
|
||||
=> x.GetParameters().Length == 1 && TypeHelper.IsTypeAssignableFrom<IFileSystem>(x.GetParameters().Single().ParameterType));
|
||||
if (constructor == null)
|
||||
throw new InvalidOperationException("Type " + fsType.FullName + " must inherit from FileSystemWrapper and have a constructor that accepts one parameter of type " + typeof(IFileSystem).FullName + ".");
|
||||
|
||||
// gets the inner fs, create the strongly-typed fs wrapping the inner fs, register & return
|
||||
// so we are double-wrapping here
|
||||
// could be optimized by having FileSystemWrapper inherit from ShadowWrapper, maybe
|
||||
var innerFs = GetUnderlyingFileSystemProvider(alias);
|
||||
var shadowWrapper = new ShadowWrapper(innerFs, "typed/" + alias, ScopeProvider);
|
||||
var fs = (TFileSystem) Activator.CreateInstance(typeof (TFileSystem), shadowWrapper);
|
||||
_wrappers.Add(shadowWrapper); // keeping a weak reference to the wrapper
|
||||
return fs;
|
||||
// find the attribute and get the alias
|
||||
var attr = (FileSystemProviderAttribute)fsType.GetCustomAttributes(typeof(FileSystemProviderAttribute), false).SingleOrDefault();
|
||||
if (attr == null)
|
||||
throw new InvalidOperationException("Type " + fsType.FullName + "is missing the required FileSystemProviderAttribute.");
|
||||
|
||||
return attr.Alias;
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -199,30 +255,37 @@ namespace Umbraco.Core.IO
|
||||
var wrappers = new ShadowWrapper[typed.Length + 7];
|
||||
var i = 0;
|
||||
while (i < typed.Length) wrappers[i] = typed[i++];
|
||||
wrappers[i++] = _macroPartialFileSystemWrapper;
|
||||
wrappers[i++] = _partialViewsFileSystemWrapper;
|
||||
wrappers[i++] = _stylesheetsFileSystemWrapper;
|
||||
wrappers[i++] = _scriptsFileSystemWrapper;
|
||||
wrappers[i++] = _xsltFileSystemWrapper;
|
||||
wrappers[i++] = _masterPagesFileSystemWrapper;
|
||||
wrappers[i] = _mvcViewsFileSystemWrapper;
|
||||
wrappers[i++] = _macroPartialFileSystem;
|
||||
wrappers[i++] = _partialViewsFileSystem;
|
||||
wrappers[i++] = _stylesheetsFileSystem;
|
||||
wrappers[i++] = _scriptsFileSystem;
|
||||
wrappers[i++] = _xsltFileSystem;
|
||||
wrappers[i++] = _masterPagesFileSystem;
|
||||
wrappers[i] = _mvcViewsFileSystem;
|
||||
|
||||
return new ShadowFileSystems(id, wrappers);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private class WeakSet<T>
|
||||
private class ConcurrentSet<T>
|
||||
where T : class
|
||||
{
|
||||
private readonly HashSet<WeakReference<T>> _set = new HashSet<WeakReference<T>>();
|
||||
private readonly HashSet<T> _set = new HashSet<T>();
|
||||
|
||||
public void Add(T item)
|
||||
{
|
||||
lock (_set)
|
||||
{
|
||||
_set.Add(new WeakReference<T>(item));
|
||||
CollectLocked();
|
||||
_set.Add(item);
|
||||
}
|
||||
}
|
||||
|
||||
public void Clear()
|
||||
{
|
||||
lock (_set)
|
||||
{
|
||||
_set.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -230,23 +293,9 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
lock (_set)
|
||||
{
|
||||
CollectLocked();
|
||||
return _set.Select(x =>
|
||||
{
|
||||
T target;
|
||||
return x.TryGetTarget(out target) ? target : null;
|
||||
}).WhereNotNull().ToArray();
|
||||
return _set.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
private void CollectLocked()
|
||||
{
|
||||
_set.RemoveWhere(x =>
|
||||
{
|
||||
T target;
|
||||
return x.TryGetTarget(out target) == false;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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" },
|
||||
@@ -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?
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Umbraco.Core.IO
|
||||
{
|
||||
@@ -209,19 +210,20 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public IEnumerable<string> GetFiles(string path)
|
||||
{
|
||||
var normPath = NormPath(path);
|
||||
var shadows = Nodes.Where(kvp => IsChild(normPath, kvp.Key)).ToArray();
|
||||
var files = _fs.GetFiles(path);
|
||||
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).Select(kvp => kvp.Key))
|
||||
.Distinct();
|
||||
return GetFiles(path, null);
|
||||
}
|
||||
|
||||
public IEnumerable<string> GetFiles(string path, string filter)
|
||||
{
|
||||
return _fs.GetFiles(path, filter);
|
||||
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 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 && (wildcard == null || wildcard.IsMatch(kvp.Key))).Select(kvp => kvp.Key))
|
||||
.Distinct();
|
||||
}
|
||||
|
||||
public Stream OpenFile(string path)
|
||||
@@ -253,6 +255,9 @@ namespace Umbraco.Core.IO
|
||||
|
||||
public string GetFullPath(string path)
|
||||
{
|
||||
ShadowNode sf;
|
||||
if (Nodes.TryGetValue(NormPath(path), out sf))
|
||||
return sf.IsDir || sf.IsDelete ? null : _sfs.GetFullPath(path);
|
||||
return _fs.GetFullPath(path);
|
||||
}
|
||||
|
||||
@@ -321,5 +326,65 @@ namespace Umbraco.Core.IO
|
||||
_sfs.AddFile(path, physicalPath, overrideIfExists, copy);
|
||||
Nodes[normPath] = new ShadowNode(false, false);
|
||||
}
|
||||
|
||||
// copied from System.Web.Util.Wildcard internal
|
||||
internal class WildcardExpression
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace Umbraco.Core.IO
|
||||
// on ShadowFileSystemsScope.None - and if None is false then we should be running
|
||||
// in a single thread anyways
|
||||
|
||||
var virt = "~/App_Data/Shadow/" + id + "/" + _shadowPath;
|
||||
var virt = "~/App_Data/TEMP/ShadowFs/" + id + "/" + _shadowPath;
|
||||
_shadowDir = IOHelper.MapPath(virt);
|
||||
Directory.CreateDirectory(_shadowDir);
|
||||
var tempfs = new PhysicalFileSystem(virt);
|
||||
@@ -69,6 +69,11 @@ namespace Umbraco.Core.IO
|
||||
{
|
||||
var isScoped = _scopeProvider != null && _scopeProvider.AmbientScope != null && _scopeProvider.AmbientScope.ScopedFileSystems;
|
||||
|
||||
// if the filesystem is created *after* shadowing starts, it won't be shadowing
|
||||
// better not ignore that situation and raised a meaningful (?) exception
|
||||
if (isScoped && _shadowFileSystem == null)
|
||||
throw new Exception("The filesystems are shadowing, but this filesystem is not.");
|
||||
|
||||
return isScoped
|
||||
? _shadowFileSystem
|
||||
: _innerFileSystem;
|
||||
|
||||
@@ -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,84 +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;
|
||||
}
|
||||
|
||||
throw new NotSupportedException("The content type must be " + typeof(IContentType) + " or " + typeof(IMediaType));
|
||||
}
|
||||
|
||||
/// <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);
|
||||
//}
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace Umbraco.Core.Models.Identity
|
||||
public override void ConfigureMappings(IConfiguration config, ApplicationContext applicationContext)
|
||||
{
|
||||
config.CreateMap<IUser, BackOfficeIdentityUser>()
|
||||
.ForMember(user => user.LastLoginDateUtc, expression => expression.MapFrom(user => user.LastLoginDate.ToUniversalTime()))
|
||||
.ForMember(user => user.Email, expression => expression.MapFrom(user => user.Email))
|
||||
.ForMember(user => user.Id, expression => expression.MapFrom(user => user.Id))
|
||||
.ForMember(user => user.LockoutEndDateUtc, expression => expression.MapFrom(user => user.IsLockedOut ? DateTime.MaxValue.ToUniversalTime() : (DateTime?)null))
|
||||
|
||||
@@ -24,12 +24,17 @@ namespace Umbraco.Core.Models.Identity
|
||||
///
|
||||
/// </summary>
|
||||
public IdentityUser()
|
||||
{
|
||||
{
|
||||
this.Claims = new List<TClaim>();
|
||||
this.Roles = new List<TRole>();
|
||||
this.Logins = new List<TLogin>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Last login date
|
||||
/// </summary>
|
||||
public virtual DateTime? LastLoginDateUtc { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Email
|
||||
///
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
internal class DataTypePreValueDto
|
||||
{
|
||||
[Column("id")]
|
||||
[PrimaryKeyColumn(IdentitySeed = 6)]
|
||||
[PrimaryKeyColumn(IdentitySeed = 10)]
|
||||
public int Id { get; set; }
|
||||
|
||||
[Column("datatypeNodeId")]
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Umbraco.Core.Models.Rdbms
|
||||
|
||||
[Column("nodeId")]
|
||||
[ForeignKey(typeof(NodeDto))]
|
||||
[Index(IndexTypes.NonClustered, Name = "IX_umbracoUser2NodePermission_nodeId")]
|
||||
public int NodeId { get; set; }
|
||||
|
||||
[Column("permission")]
|
||||
|
||||
@@ -113,6 +113,11 @@ namespace Umbraco.Core.Models
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When resolved from EntityService this checks if the entity has the HasChildren flag
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <returns></returns>
|
||||
public static bool HasChildren(this IUmbracoEntity entity)
|
||||
{
|
||||
if (entity.AdditionalData.ContainsKey("HasChildren"))
|
||||
@@ -133,6 +138,11 @@ namespace Umbraco.Core.Models
|
||||
return entity.AdditionalData.GetValueIgnoreCase(key, defaultVal);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When resolved from EntityService this checks if the entity has the IsContainer flag
|
||||
/// </summary>
|
||||
/// <param name="entity"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsContainer(this IUmbracoEntity entity)
|
||||
{
|
||||
if (entity.AdditionalData.ContainsKeyIgnoreCase("IsContainer") == false) return false;
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace Umbraco.Core.Models
|
||||
/// <summary>
|
||||
/// Root
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.SystemRoot)]
|
||||
[UmbracoObjectType(Constants.ObjectTypes.SystemRoot)]
|
||||
[FriendlyName("Root")]
|
||||
ROOT,
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.Document, typeof(IContent))]
|
||||
[FriendlyName("Document")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.Document)]
|
||||
Document,
|
||||
|
||||
/// <summary>
|
||||
@@ -42,6 +43,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.Media, typeof(IMedia))]
|
||||
[FriendlyName("Media")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.Media)]
|
||||
Media,
|
||||
|
||||
/// <summary>
|
||||
@@ -49,6 +51,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.MemberType, typeof(IMemberType))]
|
||||
[FriendlyName("Member Type")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.MemberType)]
|
||||
MemberType,
|
||||
|
||||
/// <summary>
|
||||
@@ -56,6 +59,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.Template, typeof(ITemplate))]
|
||||
[FriendlyName("Template")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.Template)]
|
||||
Template,
|
||||
|
||||
/// <summary>
|
||||
@@ -63,6 +67,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.MemberGroup)]
|
||||
[FriendlyName("Member Group")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.MemberGroup)]
|
||||
MemberGroup,
|
||||
|
||||
//TODO: What is a 'Content Item' supposed to be???
|
||||
@@ -80,6 +85,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.MediaType, typeof(IMediaType))]
|
||||
[FriendlyName("Media Type")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.MediaType)]
|
||||
MediaType,
|
||||
|
||||
/// <summary>
|
||||
@@ -87,13 +93,14 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.DocumentType, typeof(IContentType))]
|
||||
[FriendlyName("Document Type")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.DocumentType)]
|
||||
DocumentType,
|
||||
|
||||
/// <summary>
|
||||
/// Recycle Bin
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.ContentRecycleBin)]
|
||||
[FriendlyName("Recycle Bin")]
|
||||
[FriendlyName("Recycle Bin")]
|
||||
RecycleBin,
|
||||
|
||||
/// <summary>
|
||||
@@ -101,6 +108,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.Stylesheet)]
|
||||
[FriendlyName("Stylesheet")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.Stylesheet)]
|
||||
Stylesheet,
|
||||
|
||||
/// <summary>
|
||||
@@ -108,6 +116,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.Member, typeof(IMember))]
|
||||
[FriendlyName("Member")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.Member)]
|
||||
Member,
|
||||
|
||||
/// <summary>
|
||||
@@ -115,6 +124,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.DataType, typeof(IDataTypeDefinition))]
|
||||
[FriendlyName("Data Type")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.DataType)]
|
||||
DataType,
|
||||
|
||||
/// <summary>
|
||||
@@ -122,6 +132,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.DocumentTypeContainer)]
|
||||
[FriendlyName("Document Type Container")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.DocumentTypeContainer)]
|
||||
DocumentTypeContainer,
|
||||
|
||||
/// <summary>
|
||||
@@ -129,6 +140,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.MediaTypeContainer)]
|
||||
[FriendlyName("Media Type Container")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.MediaTypeContainer)]
|
||||
MediaTypeContainer,
|
||||
|
||||
/// <summary>
|
||||
@@ -136,6 +148,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.DataTypeContainer)]
|
||||
[FriendlyName("Data Type Container")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.DataTypeContainer)]
|
||||
DataTypeContainer,
|
||||
|
||||
/// <summary>
|
||||
@@ -143,6 +156,7 @@ namespace Umbraco.Core.Models
|
||||
/// </summary>
|
||||
[UmbracoObjectType(Constants.ObjectTypes.RelationType)]
|
||||
[FriendlyName("Relation Type")]
|
||||
[UmbracoUdiType(Constants.UdiEntityType.RelationType)]
|
||||
RelationType,
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace Umbraco.Core.Models
|
||||
{
|
||||
//MUST be concurrent to avoid thread collisions!
|
||||
private static readonly ConcurrentDictionary<UmbracoObjectTypes, Guid> UmbracoObjectTypeCache = new ConcurrentDictionary<UmbracoObjectTypes, Guid>();
|
||||
private static readonly ConcurrentDictionary<UmbracoObjectTypes, string> UmbracoObjectTypeUdiCache = new ConcurrentDictionary<UmbracoObjectTypes, string>();
|
||||
|
||||
/// <summary>
|
||||
/// Get an UmbracoObjectTypes value from it's name
|
||||
@@ -43,6 +44,21 @@ namespace Umbraco.Core.Models
|
||||
return umbracoObjectType;
|
||||
}
|
||||
|
||||
public static string GetUdiType(Guid guid)
|
||||
{
|
||||
var umbracoObjectType = Constants.UdiEntityType.Unknown;
|
||||
|
||||
foreach (var name in Enum.GetNames(typeof(UmbracoObjectTypes)))
|
||||
{
|
||||
var objType = GetUmbracoObjectType(name);
|
||||
if (objType.GetGuid() == guid)
|
||||
{
|
||||
umbracoObjectType = GetUdiType(objType);
|
||||
}
|
||||
}
|
||||
return umbracoObjectType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for the UmbracoObjectTypes enum to return the enum GUID
|
||||
/// </summary>
|
||||
@@ -68,6 +84,26 @@ namespace Umbraco.Core.Models
|
||||
});
|
||||
}
|
||||
|
||||
public static string GetUdiType(this UmbracoObjectTypes umbracoObjectType)
|
||||
{
|
||||
return UmbracoObjectTypeUdiCache.GetOrAdd(umbracoObjectType, types =>
|
||||
{
|
||||
var type = typeof(UmbracoObjectTypes);
|
||||
var memInfo = type.GetMember(umbracoObjectType.ToString());
|
||||
var attributes = memInfo[0].GetCustomAttributes(typeof(UmbracoUdiTypeAttribute),
|
||||
false);
|
||||
|
||||
if (attributes.Length == 0)
|
||||
return Constants.UdiEntityType.Unknown;
|
||||
|
||||
var attribute = ((UmbracoUdiTypeAttribute)attributes[0]);
|
||||
if (attribute == null)
|
||||
return Constants.UdiEntityType.Unknown;
|
||||
|
||||
return attribute.UdiType;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension method for the UmbracoObjectTypes enum to return the enum name
|
||||
/// </summary>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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];
|
||||
@@ -50,7 +51,7 @@ namespace Umbraco.Core.Persistence.Factories
|
||||
entity.ContentTypeThumbnail = asDictionary.ContainsKey("thumbnail") ? (d.thumbnail ?? string.Empty) : string.Empty;
|
||||
|
||||
var publishedVersion = default(Guid);
|
||||
//some content items don't have a published version
|
||||
//some content items don't have a published/newest version
|
||||
if (asDictionary.ContainsKey("publishedVersion") && asDictionary["publishedVersion"] != null)
|
||||
{
|
||||
Guid.TryParse(d.publishedVersion.ToString(), out publishedVersion);
|
||||
@@ -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,21 +130,21 @@ 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 = 1034, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1034", SortOrder = 2, UniqueId = new Guid("a6857c73-d6e9-480c-b6e6-f15f6ad11125"), Text = "Content Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1035, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1035", SortOrder = 2, UniqueId = new Guid("93929b9a-93a2-4e2a-b239-d99334440a59"), Text = "Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1036, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1036", SortOrder = 2, UniqueId = new Guid("2b24165f-9782-4aa3-b459-1de4a4d21f60"), Text = "Member Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), 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 });
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1045, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1045", SortOrder = 2, UniqueId = new Guid("7E3962CC-CE20-4FFC-B661-5897A894BA7E"), Text = "Multiple Media Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
|
||||
//New UDI pickers with newer Ids
|
||||
_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1046, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1046", SortOrder = 2, UniqueId = new Guid("FD1E0DA5-5606-4862-B679-5D0CF3A52A59"), Text = "Content Picker", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
_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 });
|
||||
//_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1038, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1038", SortOrder = 2, UniqueId = new Guid("1251c96c-185c-4e9b-93f4-b48205573cbd"), Text = "Simple Editor", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
|
||||
//_database.Insert("umbracoNode", "id", false, new NodeDto { NodeId = 1042, Trashed = false, ParentId = -1, UserId = 0, Level = 1, Path = "-1,1042", SortOrder = 2, UniqueId = new Guid("0a452bd5-83f9-4bc3-8403-1286e13fb77e"), Text = "Macro Container", NodeObjectType = new Guid(Constants.ObjectTypes.DataType), CreateDate = DateTime.Now });
|
||||
}
|
||||
|
||||
@@ -246,17 +246,19 @@ 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 = 16, DataTypeId = 1034, PropertyEditorAlias = Constants.PropertyEditors.ContentPickerAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 18, DataTypeId = 1036, PropertyEditorAlias = Constants.PropertyEditors.MemberPickerAlias, DbType = "Integer" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 17, DataTypeId = 1035, PropertyEditorAlias = Constants.PropertyEditors.MultipleMediaPickerAlias, 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 = 25, DataTypeId = 1045, PropertyEditorAlias = Constants.PropertyEditors.MultipleMediaPickerAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -26, DataTypeId = Constants.System.DefaultContentListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -27, DataTypeId = Constants.System.DefaultMediaListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -28, DataTypeId = Constants.System.DefaultMembersListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = -28, DataTypeId = Constants.System.DefaultMembersListViewDataTypeId, PropertyEditorAlias = Constants.PropertyEditors.ListViewAlias, DbType = "Nvarchar" });
|
||||
|
||||
//New UDI pickers with newer Ids
|
||||
_database.Insert("cmsDataType", "pk", false, new DataTypeDto { PrimaryKey = 26, DataTypeId = 1046, PropertyEditorAlias = Constants.PropertyEditors.ContentPicker2Alias, DbType = "Nvarchar" });
|
||||
_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" });
|
||||
@@ -268,10 +270,7 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
{
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 3, Alias = "", SortOrder = 0, DataTypeNodeId = -87, Value = ",code,undo,redo,cut,copy,mcepasteword,stylepicker,bold,italic,bullist,numlist,outdent,indent,mcelink,unlink,mceinsertanchor,mceimage,umbracomacro,mceinserttable,umbracoembed,mcecharmap,|1|1,2,3,|0|500,400|1049,|true|" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 4, Alias = "group", SortOrder = 0, DataTypeNodeId = 1041, Value = "default" });
|
||||
|
||||
//default's for MultipleMediaPickerAlias picker
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 5, Alias = "multiPicker", SortOrder = 0, DataTypeNodeId = 1045, Value = "1" });
|
||||
|
||||
|
||||
//defaults for the member list
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -1, Alias = "pageSize", SortOrder = 1, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "10" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -2, Alias = "orderBy", SortOrder = 2, DataTypeNodeId = Constants.System.DefaultMembersListViewDataTypeId, Value = "username" });
|
||||
@@ -288,6 +287,9 @@ namespace Umbraco.Core.Persistence.Migrations.Initial
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -7, Alias = "orderDirection", SortOrder = 3, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "desc" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -8, Alias = "layouts", SortOrder = 4, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[" + cardLayout + "," + listLayout + "]" });
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = -9, Alias = "includeProperties", SortOrder = 5, DataTypeNodeId = Constants.System.DefaultMediaListViewDataTypeId, Value = "[{\"alias\":\"updateDate\",\"header\":\"Last edited\",\"isSystem\":1},{\"alias\":\"owner\",\"header\":\"Updated by\",\"isSystem\":1}]" });
|
||||
|
||||
//default's for MultipleMediaPickerAlias picker
|
||||
_database.Insert("cmsDataTypePreValues", "id", false, new DataTypePreValueDto { Id = 6, Alias = "multiPicker", SortOrder = 0, DataTypeNodeId = 1049, Value = "1" });
|
||||
}
|
||||
|
||||
private void CreateUmbracoRelationTypeData()
|
||||
|
||||
+1
-9
@@ -1,6 +1,5 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
@@ -14,14 +13,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
var dbIndexes = SqlSyntax.GetDefinedIndexes(Context.Database)
|
||||
.Select(x => new DbIndexDefinition()
|
||||
{
|
||||
TableName = x.Item1,
|
||||
IndexName = x.Item2,
|
||||
ColumnName = x.Item3,
|
||||
IsUnique = x.Item4
|
||||
}).ToArray();
|
||||
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database);
|
||||
|
||||
//make sure it doesn't already exist
|
||||
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_cmsMember_LoginName")) == false)
|
||||
|
||||
-1
@@ -1,6 +1,5 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.DatabaseModelDefinitions;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
{
|
||||
[Migration("7.6.0", 0, Constants.System.UmbracoMigrationName)]
|
||||
public class AddIndexToUser2NodePermission : MigrationBase
|
||||
{
|
||||
public AddIndexToUser2NodePermission(ISqlSyntaxProvider sqlSyntax, ILogger logger)
|
||||
: base(sqlSyntax, logger)
|
||||
{ }
|
||||
|
||||
public override void Up()
|
||||
{
|
||||
var dbIndexes = SqlSyntax.GetDefinedIndexesDefinitions(Context.Database);
|
||||
|
||||
//make sure it doesn't already exist
|
||||
if (dbIndexes.Any(x => x.IndexName.InvariantEquals("IX_umbracoUser2NodePermission_nodeId")) == false)
|
||||
{
|
||||
Create.Index("IX_umbracoUser2NodePermission_nodeId").OnTable("umbracoUser2NodePermission")
|
||||
.OnColumn("nodeId")
|
||||
.Ascending()
|
||||
.WithOptions()
|
||||
.NonClustered();
|
||||
}
|
||||
}
|
||||
|
||||
public override void Down()
|
||||
{
|
||||
Delete.Index("IX_umbracoUser2NodePermission_nodeId").OnTable("cmsMember");
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-4
@@ -1,11 +1,10 @@
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Models.Rdbms;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveFive
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
{
|
||||
[Migration("7.5.5", 101, Constants.System.UmbracoMigrationName)]
|
||||
[Migration("7.6.0", 101, Constants.System.UmbracoMigrationName)]
|
||||
public class AddLockObjects : MigrationBase
|
||||
{
|
||||
public AddLockObjects(ISqlSyntaxProvider sqlSyntax, ILogger logger)
|
||||
+2
-3
@@ -1,11 +1,10 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenFiveFive
|
||||
namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
{
|
||||
[Migration("7.5.5", 100, Constants.System.UmbracoMigrationName)]
|
||||
[Migration("7.6.0", 100, Constants.System.UmbracoMigrationName)]
|
||||
public class AddLockTable : MigrationBase
|
||||
{
|
||||
public AddLockTable(ISqlSyntaxProvider sqlSyntax, ILogger logger)
|
||||
+2
-3
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
@@ -44,7 +43,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
private static string UpdateMacroGuids(Database database)
|
||||
{
|
||||
var updates = database.Query<dynamic>("SELECT id, macroAlias FROM cmsMacro")
|
||||
.Select(macro => Tuple.Create((int) macro.id, ((string) macro.macroAlias).ToGuid()))
|
||||
.Select(macro => Tuple.Create((int) macro.id, ("macro____" + (string) macro.macroAlias).ToGuid()))
|
||||
.ToList();
|
||||
|
||||
foreach (var update in updates)
|
||||
@@ -58,7 +57,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
var updates = database.Query<dynamic>(@"SELECT cmsMacroProperty.id id, macroPropertyAlias propertyAlias, cmsMacro.macroAlias macroAlias
|
||||
FROM cmsMacroProperty
|
||||
JOIN cmsMacro ON cmsMacroProperty.macro=cmsMacro.id")
|
||||
.Select(prop => Tuple.Create((int) prop.id, ((string) prop.macroAlias + "____" + (string) prop.propertyAlias).ToGuid()))
|
||||
.Select(prop => Tuple.Create((int) prop.id, ("macro____" + (string) prop.macroAlias + "____" + (string) prop.propertyAlias).ToGuid()))
|
||||
.ToList();
|
||||
|
||||
foreach (var update in updates)
|
||||
|
||||
+1
-2
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
@@ -32,7 +31,7 @@ namespace Umbraco.Core.Persistence.Migrations.Upgrades.TargetVersionSevenSixZero
|
||||
private static string UpdateRelationTypeGuids(Database database)
|
||||
{
|
||||
var updates = database.Query<dynamic>("SELECT id, alias, name FROM umbracoRelationType")
|
||||
.Select(relationType => Tuple.Create((int) relationType.id, ((string) relationType.alias + "____" + (string) relationType.name).ToGuid()))
|
||||
.Select(relationType => Tuple.Create((int) relationType.id, ("relationType____" + (string) relationType.alias + "____" + (string) relationType.name).ToGuid()))
|
||||
.ToList();
|
||||
|
||||
foreach (var update in updates)
|
||||
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
using System.Linq;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
|
||||
-4
@@ -1,9 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Umbraco.Core.Configuration;
|
||||
using Umbraco.Core.Logging;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
|
||||
@@ -703,7 +703,7 @@ namespace Umbraco.Core.Persistence
|
||||
|
||||
static Regex rxColumns = new Regex(@"\A\s*SELECT\s+((?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|.)*?)(?<!,\s+)\bFROM\b", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
static Regex rxOrderBy = new Regex(@"\bORDER\s+BY\s+(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?(?:\s*,\s*(?:\((?>\((?<depth>)|\)(?<-depth>)|.?)*(?(depth)(?!))\)|[\w\(\)\.])+(?:\s+(?:ASC|DESC))?)*", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
static Regex rxDistinct = new Regex(@"\ADISTINCT\s", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
static Regex rxDistinct = new Regex(@"\ADISTINCT\s", RegexOptions.IgnoreCase | RegexOptions.Multiline | RegexOptions.Singleline | RegexOptions.Compiled);
|
||||
public static bool SplitSqlForPaging(string sql, out string sqlCount, out string sqlSelectRemoved, out string sqlOrderBy)
|
||||
{
|
||||
sqlSelectRemoved = null;
|
||||
@@ -723,10 +723,9 @@ namespace Umbraco.Core.Persistence
|
||||
sqlCount = sql.Substring(0, g.Index) + "COUNT(" + m.Groups[1].ToString().Trim() + ") " + sql.Substring(g.Index + g.Length);
|
||||
else
|
||||
sqlCount = sql.Substring(0, g.Index) + "COUNT(*) " + sql.Substring(g.Index + g.Length);
|
||||
|
||||
|
||||
// Look for an "ORDER BY <whatever>" clause
|
||||
m = rxOrderBy.Match(sqlCount);
|
||||
|
||||
// Look for an "ORDER BY <whatever>" clause
|
||||
m = rxOrderBy.Match(sqlCount);
|
||||
if (!m.Success)
|
||||
{
|
||||
sqlOrderBy = null;
|
||||
@@ -737,8 +736,7 @@ namespace Umbraco.Core.Persistence
|
||||
sqlOrderBy = g.ToString();
|
||||
sqlCount = sqlCount.Substring(0, g.Index) + sqlCount.Substring(g.Index + g.Length);
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -820,7 +818,7 @@ namespace Umbraco.Core.Persistence
|
||||
result.CurrentPage = page;
|
||||
result.ItemsPerPage = itemsPerPage;
|
||||
result.TotalItems = ExecuteScalar<long>(sqlCount, args);
|
||||
result.TotalPages = result.TotalItems / itemsPerPage;
|
||||
result.TotalPages = result.TotalItems / itemsPerPage;
|
||||
if ((result.TotalItems % itemsPerPage) != 0)
|
||||
result.TotalPages++;
|
||||
|
||||
|
||||
@@ -546,7 +546,7 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
&& methodArgs.Length == 1
|
||||
&& methodArgs[0].NodeType == ExpressionType.MemberAccess
|
||||
&& TypeHelper.IsTypeAssignableFrom<IEnumerable>(m.Arguments[0].Type))
|
||||
{
|
||||
{
|
||||
goto case "SqlIn";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Linq.Expressions;
|
||||
using Umbraco.Core.Models.EntityBase;
|
||||
using Umbraco.Core.Persistence.Mappers;
|
||||
using Umbraco.Core.Persistence.SqlSyntax;
|
||||
|
||||
@@ -12,17 +13,19 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
/// <remarks>This object is stateful and cannot be re-used to parse an expression.</remarks>
|
||||
internal class ModelToSqlExpressionVisitor<T> : ExpressionVisitorBase
|
||||
{
|
||||
private readonly MappingResolver _mappingResolver;
|
||||
private readonly BaseMapper _mapper;
|
||||
|
||||
public ModelToSqlExpressionVisitor(ISqlSyntaxProvider sqlSyntax, BaseMapper mapper)
|
||||
public ModelToSqlExpressionVisitor(ISqlSyntaxProvider sqlSyntax, MappingResolver mappingResolver)
|
||||
: base(sqlSyntax)
|
||||
{
|
||||
_mapper = mapper;
|
||||
_mapper = mappingResolver.ResolveMapperByType(typeof(T));
|
||||
_mappingResolver = mappingResolver;
|
||||
}
|
||||
|
||||
[Obsolete("Use the overload the specifies a SqlSyntaxProvider")]
|
||||
public ModelToSqlExpressionVisitor()
|
||||
: this(SqlSyntaxContext.SqlSyntaxProvider, MappingResolver.Current.ResolveMapperByType(typeof(T)))
|
||||
: this(SqlSyntaxContext.SqlSyntaxProvider, MappingResolver.Current)
|
||||
{ }
|
||||
|
||||
protected override string VisitMemberAccess(MemberExpression m)
|
||||
@@ -36,7 +39,7 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
var field = _mapper.Map(m.Member.Name, true);
|
||||
if (field.IsNullOrWhiteSpace())
|
||||
throw new InvalidOperationException("The mapper returned an empty field for the member name: " + m.Member.Name);
|
||||
throw new InvalidOperationException(string.Format("The mapper returned an empty field for the member name: {0} for type: {1}", m.Member.Name, m.Expression.Type));
|
||||
return field;
|
||||
}
|
||||
//already compiled, return
|
||||
@@ -50,13 +53,42 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
{
|
||||
var field = _mapper.Map(m.Member.Name, true);
|
||||
if (field.IsNullOrWhiteSpace())
|
||||
throw new InvalidOperationException("The mapper returned an empty field for the member name: " + m.Member.Name);
|
||||
throw new InvalidOperationException(string.Format("The mapper returned an empty field for the member name: {0} for type: {1}", m.Member.Name, m.Expression.Type));
|
||||
return field;
|
||||
}
|
||||
//already compiled, return
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
if (m.Expression != null
|
||||
&& m.Expression.Type != typeof(T)
|
||||
&& TypeHelper.IsTypeAssignableFrom<IUmbracoEntity>(m.Expression.Type)
|
||||
&& EndsWithConstant(m) == false)
|
||||
{
|
||||
//if this is the case, it means we have a sub expression / nested property access, such as: x.ContentType.Alias == "Test";
|
||||
//and since the sub type (x.ContentType) is not the same as x, we need to resolve a mapper for x.ContentType to get it's mapped SQL column
|
||||
|
||||
//don't execute if compiled
|
||||
if (Visited == false)
|
||||
{
|
||||
var subMapper = _mappingResolver.ResolveMapperByType(m.Expression.Type);
|
||||
if (subMapper == null)
|
||||
throw new NullReferenceException("No mapper found for type " + m.Expression.Type);
|
||||
var field = subMapper.Map(m.Member.Name, true);
|
||||
if (field.IsNullOrWhiteSpace())
|
||||
throw new InvalidOperationException(string.Format("The mapper returned an empty field for the member name: {0} for type: {1}", m.Member.Name, m.Expression.Type));
|
||||
return field;
|
||||
}
|
||||
//already compiled, return
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
//TODO: When m.Expression.NodeType == ExpressionType.Constant and it's an expression like: content => aliases.Contains(content.ContentType.Alias);
|
||||
// then an SQL parameter will be added for aliases as an array, however in SqlIn on the subclass it will manually add these SqlParameters anyways,
|
||||
// however the query will still execute because the SQL that is written will only contain the correct indexes of SQL parameters, this would be ignored,
|
||||
// I'm just unsure right now due to time constraints how to make it correct. It won't matter right now and has been working already with this bug but I've
|
||||
// only just discovered what it is actually doing.
|
||||
|
||||
var member = Expression.Convert(m, typeof(object));
|
||||
var lambda = Expression.Lambda<Func<object>>(member);
|
||||
var getter = lambda.Compile();
|
||||
@@ -71,5 +103,24 @@ namespace Umbraco.Core.Persistence.Querying
|
||||
return string.Empty;
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determines if the MemberExpression ends in a Constant value
|
||||
/// </summary>
|
||||
/// <param name="m"></param>
|
||||
/// <returns></returns>
|
||||
private bool EndsWithConstant(MemberExpression m)
|
||||
{
|
||||
Expression expr = m;
|
||||
|
||||
while (expr is MemberExpression)
|
||||
{
|
||||
var memberExpr = expr as MemberExpression;
|
||||
expr = memberExpr.Expression;
|
||||
}
|
||||
|
||||
var constExpr = expr as ConstantExpression;
|
||||
return constExpr != null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (dto == null)
|
||||
return null;
|
||||
|
||||
var content = CreateContentFromDto(dto, dto.ContentVersionDto.VersionId, sql);
|
||||
var content = CreateContentFromDto(dto, sql);
|
||||
|
||||
return content;
|
||||
}
|
||||
@@ -134,6 +134,9 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
.On<ContentVersionDto, ContentDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<NodeDto>(SqlSyntax)
|
||||
.On<ContentDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId);
|
||||
//TODO: IF we want to enable querying on content type information this will need to be joined
|
||||
//.InnerJoin<ContentTypeDto>(SqlSyntax)
|
||||
//.On<ContentDto, ContentTypeDto>(SqlSyntax, left => left.ContentTypeId, right => right.NodeId, SqlSyntax);
|
||||
|
||||
if (queryType == BaseQueryType.FullSingle)
|
||||
{
|
||||
@@ -260,6 +263,39 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
baseId = xmlItems[xmlItems.Count - 1].NodeId;
|
||||
}
|
||||
|
||||
//now delete the items that shouldn't be there
|
||||
var sqlAllIds = translate(0, GetBaseQuery(BaseQueryType.Ids));
|
||||
var allContentIds = Database.Fetch<int>(sqlAllIds);
|
||||
var docObjectType = Guid.Parse(Constants.ObjectTypes.Document);
|
||||
var xmlIdsQuery = new Sql()
|
||||
.Select("DISTINCT cmsContentXml.nodeId")
|
||||
.From<ContentXmlDto>(SqlSyntax)
|
||||
.InnerJoin<NodeDto>(SqlSyntax)
|
||||
.On<ContentXmlDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId);
|
||||
|
||||
if (contentTypeIdsA.Length > 0)
|
||||
{
|
||||
xmlIdsQuery.InnerJoin<ContentDto>(SqlSyntax)
|
||||
.On<ContentDto, NodeDto>(SqlSyntax, left => left.NodeId, right => right.NodeId)
|
||||
.InnerJoin<ContentTypeDto>(SqlSyntax)
|
||||
.On<ContentTypeDto, ContentDto>(SqlSyntax, left => left.NodeId, right => right.ContentTypeId)
|
||||
.WhereIn<ContentDto>(x => x.ContentTypeId, contentTypeIdsA, SqlSyntax);
|
||||
}
|
||||
|
||||
xmlIdsQuery.Where<NodeDto>(dto => dto.NodeObjectType == docObjectType, SqlSyntax);
|
||||
|
||||
var allXmlIds = Database.Fetch<int>(xmlIdsQuery);
|
||||
|
||||
var toRemove = allXmlIds.Except(allContentIds).ToArray();
|
||||
if (toRemove.Length > 0)
|
||||
{
|
||||
foreach (var idGroup in toRemove.InGroupsOf(2000))
|
||||
{
|
||||
Database.Execute("DELETE FROM cmsContentXml WHERE nodeId IN (@ids)", new { ids = idGroup });
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public override IEnumerable<IContent> GetAllVersions(int id)
|
||||
@@ -273,12 +309,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sqlFull = translate(GetBaseQuery(BaseQueryType.FullMultiple));
|
||||
var sqlIds = translate(GetBaseQuery(BaseQueryType.Ids));
|
||||
|
||||
return ProcessQuery(sqlFull, new PagingSqlQuery(sqlIds), true);
|
||||
return ProcessQuery(sqlFull, new PagingSqlQuery(sqlIds), true, includeAllVersions:true);
|
||||
}
|
||||
|
||||
public override IContent GetByVersion(Guid versionId)
|
||||
{
|
||||
var sql = GetBaseQuery(BaseQueryType.FullSingle);
|
||||
//TODO: cmsContentVersion.VersionId has a Unique Index constraint applied, seems silly then to also add OrderByDescending since it would be impossible to return more than one.
|
||||
sql.Where("cmsContentVersion.VersionId = @VersionId", new { VersionId = versionId });
|
||||
sql.OrderByDescending<ContentVersionDto>(x => x.VersionDate, SqlSyntax);
|
||||
|
||||
@@ -287,7 +324,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
if (dto == null)
|
||||
return null;
|
||||
|
||||
var content = CreateContentFromDto(dto, versionId, sql);
|
||||
var content = CreateContentFromDto(dto, sql);
|
||||
|
||||
return content;
|
||||
}
|
||||
@@ -297,7 +334,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sql = new Sql()
|
||||
.Select("*")
|
||||
.From<DocumentDto>(SqlSyntax)
|
||||
.InnerJoin<ContentVersionDto>(SqlSyntax).On<ContentVersionDto, DocumentDto>(SqlSyntax, left => left.VersionId, right => right.VersionId)
|
||||
.InnerJoin<ContentVersionDto>(SqlSyntax)
|
||||
.On<ContentVersionDto, DocumentDto>(SqlSyntax, left => left.VersionId, right => right.VersionId)
|
||||
.Where<ContentVersionDto>(x => x.VersionId == versionId, SqlSyntax)
|
||||
.Where<DocumentDto>(x => x.Newest != true, SqlSyntax);
|
||||
var dto = Database.Fetch<DocumentDto, ContentVersionDto>(sql).FirstOrDefault();
|
||||
@@ -317,7 +355,8 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
var sql = new Sql()
|
||||
.Select("*")
|
||||
.From<DocumentDto>()
|
||||
.InnerJoin<ContentVersionDto>().On<ContentVersionDto, DocumentDto>(left => left.VersionId, right => right.VersionId)
|
||||
.InnerJoin<ContentVersionDto>()
|
||||
.On<ContentVersionDto, DocumentDto>(left => left.VersionId, right => right.VersionId)
|
||||
.Where<ContentVersionDto>(x => x.NodeId == id)
|
||||
.Where<ContentVersionDto>(x => x.VersionDate < versionDate)
|
||||
.Where<DocumentDto>(x => x.Newest != true);
|
||||
@@ -474,11 +513,13 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
||||
{
|
||||
VersionId = dto.VersionId,
|
||||
VersionDate = dto.UpdateDate,
|
||||
Newest = true,
|
||||
NodeId = dto.NodeId,
|
||||
Published = true
|
||||
Published = true
|
||||
};
|
||||
((Content)entity).PublishedVersionGuid = dto.VersionId;
|
||||
((Content) entity).PublishedVersionGuid = dto.VersionId;
|
||||
((Content) entity).PublishedDate = dto.UpdateDate;
|
||||
}
|
||||
|
||||
entity.ResetDirtyProperties();
|
||||
@@ -558,6 +599,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
//if (((ICanBeDirty)entity).IsPropertyDirty("Published") && (entity.Published || publishedState == PublishedState.Unpublished))
|
||||
if (entity.ShouldClearPublishedFlagForPreviousVersions(publishedState, shouldCreateNewVersion))
|
||||
{
|
||||
//TODO: This perf can be improved, it could easily be UPDATE WHERE.... (one SQL call instead of many)
|
||||
var publishedDocs = Database.Fetch<DocumentDto>("WHERE nodeId = @Id AND published = @IsPublished", new { Id = entity.Id, IsPublished = true });
|
||||
foreach (var doc in publishedDocs)
|
||||
{
|
||||
@@ -571,6 +613,7 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
}
|
||||
|
||||
//Look up (newest) entries by id in cmsDocument table to set newest = false
|
||||
//TODO: This perf can be improved, it could easily be UPDATE WHERE.... (one SQL call instead of many)
|
||||
var documentDtos = Database.Fetch<DocumentDto>("WHERE nodeId = @Id AND newest = @IsNewest", new { Id = entity.Id, IsNewest = true });
|
||||
foreach (var documentDto in documentDtos)
|
||||
{
|
||||
@@ -647,22 +690,26 @@ namespace Umbraco.Core.Persistence.Repositories
|
||||
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
||||
{
|
||||
VersionId = dto.VersionId,
|
||||
VersionDate = dto.UpdateDate,
|
||||
Newest = true,
|
||||
NodeId = dto.NodeId,
|
||||
Published = true
|
||||
};
|
||||
((Content)entity).PublishedVersionGuid = dto.VersionId;
|
||||
((Content) entity).PublishedVersionGuid = dto.VersionId;
|
||||
((Content) entity).PublishedDate = dto.UpdateDate;
|
||||
}
|
||||
else if (publishedStateChanged)
|
||||
{
|
||||
dto.DocumentPublishedReadOnlyDto = new DocumentPublishedReadOnlyDto
|
||||
{
|
||||
VersionId = default(Guid),
|
||||
VersionId = default (Guid),
|
||||
VersionDate = default (DateTime),
|
||||
Newest = false,
|
||||
NodeId = dto.NodeId,
|
||||
Published = false
|
||||
};
|
||||
((Content)entity).PublishedVersionGuid = default(Guid);
|
||||
((Content) entity).PublishedVersionGuid = default(Guid);
|
||||
((Content) entity).PublishedDate = default (DateTime);
|
||||
}
|
||||
|
||||
entity.ResetDirtyProperties();
|
||||
@@ -785,13 +832,8 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
|
||||
|
||||
public void ClearPublished(IContent content)
|
||||
{
|
||||
// race cond!
|
||||
var documentDtos = Database.Fetch<DocumentDto>("WHERE nodeId=@id AND published=@published", new { id = content.Id, published = true });
|
||||
foreach (var documentDto in documentDtos)
|
||||
{
|
||||
documentDto.Published = false;
|
||||
Database.Update(documentDto);
|
||||
}
|
||||
var sql = "UPDATE cmsDocument SET published=0 WHERE nodeId=@id AND published=1";
|
||||
Database.Execute(sql, new {id = content.Id});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -903,7 +945,7 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
|
||||
|
||||
return base.GetDatabaseFieldNameForOrderBy(orderBy);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This is the underlying method that processes most queries for this repository
|
||||
/// </summary>
|
||||
@@ -914,8 +956,12 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
|
||||
/// The Id SQL without the outer join to just return all document ids - used to process the properties for the content item
|
||||
/// </param>
|
||||
/// <param name="withCache"></param>
|
||||
/// <param name="includeAllVersions">
|
||||
/// Generally when querying for content we only want to return the most recent version of the content item, however in some cases like when
|
||||
/// we want to return all versions of a content item, we can't simply return the latest
|
||||
/// </param>
|
||||
/// <returns></returns>
|
||||
private IEnumerable<IContent> ProcessQuery(Sql sqlFull, PagingSqlQuery pagingSqlQuery, bool withCache = false)
|
||||
private IEnumerable<IContent> ProcessQuery(Sql sqlFull, PagingSqlQuery pagingSqlQuery, bool withCache = false, bool includeAllVersions = false)
|
||||
{
|
||||
// fetch returns a list so it's ok to iterate it in this method
|
||||
var dtos = Database.Fetch<DocumentDto, ContentVersionDto, ContentDto, NodeDto>(sqlFull);
|
||||
@@ -934,13 +980,12 @@ order by umbracoNode.{2}, umbracoNode.parentID, umbracoNode.sortOrder",
|
||||
parsedOriginalSql = parsedOriginalSql.Substring(0, parsedOriginalSql.LastIndexOf("ORDER BY ", StringComparison.Ordinal));
|
||||
}
|
||||
|
||||
var publishedSql = new Sql(@"SELECT *
|
||||
FROM cmsDocument AS doc2
|
||||
INNER JOIN
|
||||
(" + parsedOriginalSql + @") as docData
|
||||
ON doc2.nodeId = docData.nodeId
|
||||
WHERE doc2.published = 1
|
||||
ORDER BY doc2.nodeId
|
||||
//order by update date DESC, if there is corrupted published flags we only want the latest!
|
||||
var publishedSql = new Sql(@"SELECT cmsDocument.nodeId, cmsDocument.published, cmsDocument.versionId, cmsDocument.updateDate, cmsDocument.newest
|
||||
FROM cmsDocument INNER JOIN cmsContentVersion ON cmsContentVersion.VersionId = cmsDocument.versionId
|
||||
WHERE cmsDocument.published = 1 AND cmsDocument.nodeId IN
|
||||
(" + parsedOriginalSql + @")
|
||||
ORDER BY cmsContentVersion.id DESC
|
||||
", sqlFull.Arguments);
|
||||
|
||||
//go and get the published version data, we do a Query here and not a Fetch so we are
|
||||
@@ -955,9 +1000,9 @@ ORDER BY doc2.nodeId
|
||||
publishedDataCollection.Add(publishedDto);
|
||||
}
|
||||
|
||||
|
||||
var content = new IContent[dtos.Count];
|
||||
var defs = new List<DocumentDefinition>();
|
||||
//This is a tuple list identifying if the content item came from the cache or not
|
||||
var content = new List<Tuple<IContent, bool>>();
|
||||
var defs = new DocumentDefinitionCollection(includeAllVersions);
|
||||
var templateIds = new List<int>();
|
||||
|
||||
//track the looked up content types, even though the content types are cached
|
||||
@@ -965,9 +1010,8 @@ ORDER BY doc2.nodeId
|
||||
// the overhead of deep cloning them on every item in this loop
|
||||
var contentTypes = new Dictionary<int, IContentType>();
|
||||
|
||||
for (var i = 0; i < dtos.Count; i++)
|
||||
foreach (var dto in dtos)
|
||||
{
|
||||
var dto = dtos[i];
|
||||
DocumentPublishedReadOnlyDto publishedDto;
|
||||
publishedDataCollection.TryGetValue(dto.NodeId, out publishedDto);
|
||||
|
||||
@@ -975,10 +1019,10 @@ ORDER BY doc2.nodeId
|
||||
if (withCache)
|
||||
{
|
||||
var cached = IsolatedCache.GetCacheItem<IContent>(GetCacheIdKey<IContent>(dto.NodeId));
|
||||
//only use this cached version if the dto returned is also the publish version, they must match
|
||||
if (cached != null && cached.Published && dto.Published)
|
||||
//only use this cached version if the dto returned is also the publish version, they must match and be teh same version
|
||||
if (cached != null && cached.Version == dto.VersionId && cached.Published && dto.Published)
|
||||
{
|
||||
content[i] = cached;
|
||||
content.Add(new Tuple<IContent, bool>(cached, true));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
@@ -996,21 +1040,16 @@ ORDER BY doc2.nodeId
|
||||
contentType = _contentTypeRepository.Get(dto.ContentVersionDto.ContentDto.ContentTypeId);
|
||||
contentTypes[dto.ContentVersionDto.ContentDto.ContentTypeId] = contentType;
|
||||
}
|
||||
|
||||
content[i] = ContentFactory.BuildEntity(dto, contentType, publishedDto);
|
||||
|
||||
// need template
|
||||
if (dto.TemplateId.HasValue && dto.TemplateId.Value > 0)
|
||||
templateIds.Add(dto.TemplateId.Value);
|
||||
// track the definition and if it's successfully added or updated then processed
|
||||
if (defs.AddOrUpdate(new DocumentDefinition(dto, contentType)))
|
||||
{
|
||||
// assign template
|
||||
if (dto.TemplateId.HasValue && dto.TemplateId.Value > 0)
|
||||
templateIds.Add(dto.TemplateId.Value);
|
||||
|
||||
// need properties
|
||||
defs.Add(new DocumentDefinition(
|
||||
dto.NodeId,
|
||||
dto.VersionId,
|
||||
dto.ContentVersionDto.VersionDate,
|
||||
dto.ContentVersionDto.ContentDto.NodeDto.CreateDate,
|
||||
contentType
|
||||
));
|
||||
content.Add(new Tuple<IContent, bool>(ContentFactory.BuildEntity(dto, contentType, publishedDto), false));
|
||||
}
|
||||
}
|
||||
|
||||
// load all required templates in 1 query
|
||||
@@ -1020,38 +1059,38 @@ ORDER BY doc2.nodeId
|
||||
// load all properties for all documents from database in 1 query
|
||||
var propertyData = GetPropertyCollection(pagingSqlQuery, defs);
|
||||
|
||||
// assign
|
||||
var dtoIndex = 0;
|
||||
foreach (var def in defs)
|
||||
// assign template and property data
|
||||
foreach (var contentItem in content)
|
||||
{
|
||||
// move to corresponding item (which has to exist)
|
||||
while (dtos[dtoIndex].NodeId != def.Id) dtoIndex++;
|
||||
var cc = contentItem.Item1;
|
||||
var fromCache = contentItem.Item2;
|
||||
|
||||
//if this has come from cache, we do not need to build up it's structure
|
||||
if (fromCache) continue;
|
||||
|
||||
var def = defs[includeAllVersions ? (ValueType)cc.Version : cc.Id];
|
||||
|
||||
// complete the item
|
||||
var cc = content[dtoIndex];
|
||||
var dto = dtos[dtoIndex];
|
||||
ITemplate template = null;
|
||||
if (dto.TemplateId.HasValue)
|
||||
templates.TryGetValue(dto.TemplateId.Value, out template); // else null
|
||||
if (def.DocumentDto.TemplateId.HasValue)
|
||||
templates.TryGetValue(def.DocumentDto.TemplateId.Value, out template); // else null
|
||||
cc.Template = template;
|
||||
cc.Properties = propertyData[cc.Id];
|
||||
cc.Properties = propertyData[cc.Version];
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
cc.ResetDirtyProperties(false);
|
||||
}
|
||||
|
||||
return content;
|
||||
return content.Select(x => x.Item1).ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Private method to create a content object from a DocumentDto, which is used by Get and GetByVersion.
|
||||
/// </summary>
|
||||
/// <param name="dto"></param>
|
||||
/// <param name="versionId"></param>
|
||||
/// <param name="docSql"></param>
|
||||
/// <returns></returns>
|
||||
private IContent CreateContentFromDto(DocumentDto dto, Guid versionId, Sql docSql)
|
||||
private IContent CreateContentFromDto(DocumentDto dto, Sql docSql)
|
||||
{
|
||||
var contentType = _contentTypeRepository.Get(dto.ContentVersionDto.ContentDto.ContentTypeId);
|
||||
|
||||
@@ -1063,11 +1102,11 @@ ORDER BY doc2.nodeId
|
||||
content.Template = _templateRepository.Get(dto.TemplateId.Value);
|
||||
}
|
||||
|
||||
var docDef = new DocumentDefinition(dto.NodeId, versionId, content.UpdateDate, content.CreateDate, contentType);
|
||||
var docDef = new DocumentDefinition(dto, contentType);
|
||||
|
||||
var properties = GetPropertyCollection(docSql, new[] { docDef });
|
||||
|
||||
content.Properties = properties[dto.NodeId];
|
||||
content.Properties = properties[dto.VersionId];
|
||||
|
||||
//on initial construction we don't want to have dirty properties tracked
|
||||
// http://issues.umbraco.org/issue/U4-1946
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user