diff --git a/.deployment b/.deployment
index a7670e85780..2b834f52abb 100644
--- a/.deployment
+++ b/.deployment
@@ -1,3 +1,34 @@
+; .deployment is actually an INI file and parsed by the following file
+; https://raw.githubusercontent.com/projectkudu/kudu/master/Kudu.Core/Infrastructure/IniFile.cs
+
+; Document of deployment with custom script
+; https://github.com/projectkudu/kudu/wiki/Customizing-deployments#deploying-with-custom-script
+
+; Document of configurable settings https://github.com/projectkudu/kudu/wiki/Configurable-settings
+; Runtime settings cannot be overridden in .deployment e.g. WEBSITE_NODE_DEFAULT_VERSION
+; More info https://github.com/projectkudu/kudu/wiki/Configurable-settings#runtime-settings
+
+# Define default node version in WEBSITE_NODE_DEFAULT_VERSION APP Setting
+# Find all Node.js versions from your AppService Kudu api/diagnostics/runtime
+# More info https://codesanook-reactjs-server-side-rendering.scm.azurewebsites.net/api/diagnostics/runtime
+
+; You can define a custom environment variable as
+; CUSTOM_VARIABLE = my custom variable value
+; and read in a deploy.ps1 script as
+; $Env:CUSTOM_VARIABLE
+
+; https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe?view=powershell-5.1#examples
[config]
-command = deploy.cmd
+COMMAND = PowerShell -NoProfile -NoLogo -ExecutionPolicy Unrestricted -Command "& "$(Join-Path -Path $(Get-Location) -ChildPath deploy.ps1)" 2>&1 | Write-Output"
+
+; Set additional environment variables
+; Timeout in seconds
+; Set to one hour
SCM_COMMAND_IDLE_TIMEOUT = 3600
+
+; Variables for MSBuild
+MSBUILD_PATH = D:\Program Files (x86)\MSBuild-16.4\MSBuild\Current\Bin\MSBuild.exe
+SOLUTION_PATH = src/Orchard.sln
+
+; For Azure deployment, we use custom MS Build at root of the project.
+PROJECT_PATH = Orchard.proj
diff --git a/.github/workflows/build-crowdin-translation-packages.yml b/.github/workflows/build-crowdin-translation-packages.yml
new file mode 100644
index 00000000000..25e57af7338
--- /dev/null
+++ b/.github/workflows/build-crowdin-translation-packages.yml
@@ -0,0 +1,30 @@
+name: Build Crowdin Translation Packages
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: "0 6 * * *"
+
+jobs:
+ build-crowdin-translation-packages:
+ defaults:
+ run:
+ shell: pwsh
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Orchard CMS
+ uses: andrii-bodnar/crowdin-request-action@aac9a865d62b37060b0ce530db5ac5cfca02dd2c # 0.0.2
+ with:
+ route: POST /projects/{projectId}/translations/builds
+ projectId: 46524
+ env:
+ CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_API_TOKEN }}
+
+ - name: Orchard CMS Gallery
+ uses: andrii-bodnar/crowdin-request-action@aac9a865d62b37060b0ce530db5ac5cfca02dd2c # 0.0.2
+ with:
+ route: POST /projects/{projectId}/translations/builds
+ projectId: 63766
+ env:
+ CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_API_TOKEN }}
diff --git a/.github/workflows/compile.yml b/.github/workflows/compile.yml
new file mode 100644
index 00000000000..c8a38d39aaf
--- /dev/null
+++ b/.github/workflows/compile.yml
@@ -0,0 +1,70 @@
+name: Compile
+# Compiles the solution and runs unit tests.
+
+on:
+ workflow_dispatch:
+ pull_request:
+ push:
+ branches:
+ - dev
+ - 1.10.x
+
+jobs:
+ compile-dotnet:
+ name: Compile .NET solution
+ defaults:
+ run:
+ shell: pwsh
+ runs-on: windows-latest
+ steps:
+ - name: Clone repository
+ uses: actions/checkout@v4.1.1
+
+ - name: Restore NuGet packages
+ run: nuget restore src/Orchard.sln
+
+ - name: Add msbuild to PATH
+ uses: microsoft/setup-msbuild@v2
+
+ - name: Compile
+ run: msbuild Orchard.proj /m /v:minimal /t:Compile /p:MvcBuildViews=true /p:TreatWarningsAsErrors=true -WarnAsError
+
+ - name: Test
+ run: msbuild Orchard.proj /m /v:minimal /t:Test
+
+ compile-node:
+ name: Compile client-side assets
+ defaults:
+ run:
+ shell: pwsh
+ runs-on: windows-latest
+ steps:
+ - name: Clone repository
+ uses: actions/checkout@v4.1.1
+
+ - name: Setup NodeJS
+ uses: actions/setup-node@v4.0.2
+ with:
+ node-version: '7'
+
+ - name: Setup NPM packages
+ working-directory: ./src
+ run: |
+ npm install --loglevel warn
+
+ # Install gulp globally to be able to run the rebuild task, using the same version as in the project.
+ $gulpVersion = (Get-Content Package.json -Raw | ConvertFrom-Json).devDependencies.gulp
+ Start-Process npm -NoNewWindow -Wait -ArgumentList "install gulp@$gulpVersion -g --loglevel warn"
+
+ - name: Rebuild client-side assets
+ working-directory: ./src
+ run: |
+ gulp rebuild
+
+ git add . # To make line ending changes "disappear".
+ $gitStatus = (git status --porcelain)
+ if ($gitStatus)
+ {
+ throw ("Client-side assets are not up-to-date. Please run 'gulp rebuild' and commit the changes.`n" +
+ [System.String]::Join([System.Environment]::NewLine, $gitStatus))
+ }
diff --git a/.github/workflows/specflow.yml b/.github/workflows/specflow.yml
new file mode 100644
index 00000000000..93ab66a64d0
--- /dev/null
+++ b/.github/workflows/specflow.yml
@@ -0,0 +1,39 @@
+name: SpecFlow tests
+# Compiles the solution and runs unit tests, as well the SpecFlow tests on the main development branches.
+
+on:
+ workflow_dispatch:
+ schedule:
+ - cron: '0 0 * * *' # Every day at midnight.
+
+jobs:
+ compile:
+ name: SpecFlow tests
+ defaults:
+ run:
+ shell: pwsh
+ runs-on: windows-latest
+ strategy:
+ matrix:
+ branch: [dev, 1.10.x]
+
+ steps:
+ - name: Clone repository
+ uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
+ with:
+ ref: ${{ matrix.branch }}
+
+ - name: Restore NuGet packages
+ run: nuget restore src/Orchard.sln
+
+ - name: Add msbuild to PATH
+ uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2.0.0
+
+ - name: Compile
+ run: msbuild Orchard.proj /m /v:minimal /t:Compile /p:MvcBuildViews=true /p:TreatWarningsAsErrors=true -WarnAsError
+
+ - name: Test
+ run: msbuild Orchard.proj /m /v:minimal /t:Test
+
+ - name: Spec
+ run: msbuild Orchard.proj /m /v:minimal /t:Spec
diff --git a/.gitignore b/.gitignore
index be6a64c1eea..a22dca49fda 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,7 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
+**/.vs/**
+src/Rebracer.xml
# User-specific files
*.suo
@@ -190,5 +192,3 @@ src/Orchard.Azure/Orchard.Azure.CloudService/Staging/
#enable all /lib artifacts
!lib/**/*.*
-**/.vs/*
-src/Rebracer.xml
diff --git a/CREDITS.txt b/CREDITS.txt
index 51194d0d68b..216e1d7123b 100644
--- a/CREDITS.txt
+++ b/CREDITS.txt
@@ -187,15 +187,15 @@ License: Apache Software Foundation License 2.0
Lucene.net
-----
-Website: http://incubator.apache.org/projects/lucene.net.html
+Website: https://lucenenet.apache.org/
Copyright: Copyright (c) 2009 Apache Software Foundation
License: Apache Software Foundation License 2.0
-MarkdownSharp
+Markdig
-----
-Website: http://code.google.com/p/markdownsharp/
-Copyright: Copyright (c) 2009-2011 Jeff Atwood
-License: MIT
+Website: https://github.com/lunet-io/markdig
+Copyright: Copyright (c) 2018-2019, Alexandre Mutel
+License: BSD 2-Clause
Mono Class Library
-----
@@ -293,4 +293,4 @@ YUI
-----
Website: http://developer.yahoo.com/yui/
Copyright: Copyright (c) 2010, Yahoo! Inc.
-License: New BSD
\ No newline at end of file
+License: New BSD
diff --git a/CalculateBindingRedirects.ps1 b/CalculateBindingRedirects.ps1
new file mode 100644
index 00000000000..45f279b3f09
--- /dev/null
+++ b/CalculateBindingRedirects.ps1
@@ -0,0 +1,34 @@
+[Reflection.Assembly]::LoadWithPartialName("System.Xml") | Out-Null
+[Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq") | Out-Null
+[System.Xml.Linq.XNamespace]$ns1 = "urn:schemas-microsoft-com:asm.v1"
+
+$currentPath = (Get-Item -Path ".\").FullName
+$orchardWebConfigFullPath = $currentPath+"\src\Orchard.Web\Web.Config"
+[XML] $orchardWebConfig = Get-Content ($orchardWebConfigFullPath)
+$configFiles = Get-ChildItem -Path ($currentPath +"\src\") -Filter web.config -Recurse -ErrorAction SilentlyContinue -Force
+foreach ($configFile in $configFiles) {
+ $configFullPath = $configFile.FullName
+ Write-Host "Processing $configFullPath ..."
+
+ if ($configFullPath.ToLower().EndsWith("\orchard.web\web.config")) { #skip orchard.web config files
+ continue
+ }
+ [XML] $projectWebConfig = Get-Content ($configFullPath)
+ $elements = $projectWebConfig.configuration.runtime.assemblyBinding.dependentAssembly
+ foreach ($element in $elements){
+ Write-Host "Checking" $element.assemblyIdentity.name
+ $hasBinding = $orchardWebConfig.configuration.runtime.assemblyBinding.dependentAssembly.assemblyIdentity.Where({ $_.name -eq $element.assemblyIdentity.name -and $_.publicKeyToken -eq $element.assemblyIdentity.publicKeyToken -and $_.culture -eq $element.assemblyIdentity.culture }, 'First').Count -gt 0
+ if (-not $hasBinding){
+ # add the node in $webConfig
+ Write-Host "Adding" $element.assemblyIdentity.name
+ $newNode = $orchardWebConfig.ImportNode($element, $true);
+ $orchardWebConfig.configuration.runtime.assemblyBinding.AppendChild($newNode)
+ Write-Host "Added " $element.assemblyIdentity.name
+ } else {
+ Write-Host "Skipped" $element.assemblyIdentity.name
+ }
+ }
+ Write-Host "Processed $configFullPath ..."
+}
+
+$orchardWebConfig.Save($orchardWebConfigFullPath)
diff --git a/ClickToBuild.cmd b/ClickToBuild.cmd
index 8c5a5183402..920481b6971 100644
--- a/ClickToBuild.cmd
+++ b/ClickToBuild.cmd
@@ -1,31 +1,18 @@
-FOR %%b in (
- "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat"
- "%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
- "%ProgramFiles%\Microsoft Visual Studio 14.0\VC\vcvarsall.bat"
-
- "%VS120COMNTOOLS%..\..\VC\vcvarsall.bat"
- "%ProgramFiles(x86)%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"
- "%ProgramFiles%\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"
-
- "%VS110COMNTOOLS%..\..\VC\vcvarsall.bat"
- "%ProgramFiles(x86)%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"
- "%ProgramFiles%\Microsoft Visual Studio 11.0\VC\vcvarsall.bat"
- ) do (
- if exist %%b (
- call %%b x86
- goto build
- )
-)
-
-FOR %%b in (
- "%VS140COMNTOOLS%\vsvars32.bat"
- "%VS120COMNTOOLS%\vsvars32.bat"
- "%VS110COMNTOOLS%\vsvars32.bat"
- ) do (
- if exist %%b (
- call %%b
- goto build
- )
+@echo off
+
+REM Necessary for the InstallDir variable to work inside the MsBuild-finding loop below.
+SETLOCAL ENABLEDELAYEDEXPANSION
+
+for /f "usebackq tokens=1* delims=: " %%i in (`lib\vswhere\vswhere -latest -version "[16.0,18.0)" -requires Microsoft.Component.MSBuild`) do (
+ if /i "%%i"=="installationPath" (
+ set InstallDir=%%j
+ echo !InstallDir!
+ if exist "!InstallDir!\MSBuild\Current\Bin\MSBuild.exe" (
+ echo "Using MSBuild from !InstallDir!"
+ set msbuild="!InstallDir!\MSBuild\Current\Bin\MSBuild.exe"
+ goto build
+ )
+ )
)
echo "Unable to detect suitable environment. Build may not succeed."
@@ -42,6 +29,8 @@ IF "%solution%" == "" SET solution=src\Orchard.sln
lib\nuget\nuget.exe restore %solution%
-msbuild /t:%target% %project% /p:Solution=%solution% /m
+%msbuild% /t:%target% %project% /p:Solution=%solution% /m
+
+:end
pause
\ No newline at end of file
diff --git a/DeploymentUtility.psm1 b/DeploymentUtility.psm1
new file mode 100644
index 00000000000..01dd0678074
--- /dev/null
+++ b/DeploymentUtility.psm1
@@ -0,0 +1,83 @@
+Set-StrictMode -Version Latest
+
+# Continue a build process even though there is a warning wrote to std err.
+# We will check exit code in Invoke-ExternalCommand to design whether it fail or not
+$ErrorActionPreference = "Continue"
+
+function Add-NpmToPathVariable {
+ $path = "$env:Appdata\npm"
+ $escapedPath = [Regex]::Escape($path)
+
+ # Remove existing npm path safe to add npm path again
+ $paths = $env:Path -split ';' | Where-Object {
+ $_ -notmatch "^$escapedPath\\?$"
+ }
+
+ # Update a path variable to this session
+ $env:Path = ($paths + $path) -join ";" # array + element item
+}
+
+function Invoke-ExternalCommand {
+ param (
+ [Parameter(Mandatory = $true)] [scriptblock] $ScriptBlock
+ )
+
+ # Displays an error message and continue executing if there is a standard error.
+ # This is because there are some external command tools write warning message to standard error.
+ # Use Write-Output also fix "Window title cannot be longer than 1023 characters" issue
+ # https://github.com/projectkudu/kudu/issues/2635
+ & $ScriptBlock 2>&1 | Write-Output
+
+ # If last exit code is not 0, throw an exception to stop a script
+ if ($LastExitCode) {
+ throw "Failed with exit code = $LastExitCode and command = $($ScriptBlock.ToString())"
+ }
+}
+
+function Write-EnviromentValue {
+ param (
+ [Parameter(Mandatory = $true)] [String[]] $EnvironmentName
+ )
+
+ "----------------- Begin of environment variables ---------------------------------"
+ Get-Item -Path Env:* | Where-Object {
+ $EnvironmentName -contains $_.Name
+ } | Format-Table Name, Value -Wrap
+
+ "----------------- End of environment variables ---------------------------------"
+}
+
+function Install-Yarn {
+ "Verify if yarn installed"
+ if (Get-Command -Name yarn -ErrorAction Ignore) {
+ "Updating yarn as a global tool to the latest version"
+ # https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd#parameters
+ # issue https://github.com/projectkudu/kudu/issues/2635
+ Invoke-ExternalCommand -ScriptBlock { npm update yarn -g }
+ }
+ else {
+ "Installing yarn as a global tool"
+ Invoke-ExternalCommand -ScriptBlock { npm install yarn -g }
+ Add-NpmToPathVariable
+ }
+}
+
+function Install-KuduSync {
+ "Verify if kudusync installed"
+ if (Get-Command -Name kudusync -ErrorAction Ignore) {
+ "Updating kudusync as a global tool to the latest version"
+ # https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/cmd#parameters
+ # issue https://github.com/projectkudu/kudu/issues/2635
+ Invoke-ExternalCommand -ScriptBlock { npm update kudusync -g }
+ }
+ else {
+ "Installing kudusync as a global tool"
+ Invoke-ExternalCommand -ScriptBlock { npm install kudusync -g }
+ Add-NpmToPathVariable
+ }
+}
+
+Export-ModuleMember -Function Invoke-ExternalCommand
+Export-ModuleMember -Function Write-EnviromentValue
+Export-ModuleMember -Function Install-Yarn
+Export-ModuleMember -Function Install-KuduSync
diff --git a/Orchard.proj b/Orchard.proj
index 25004a059f7..0f5cfbc8022 100644
--- a/Orchard.proj
+++ b/Orchard.proj
@@ -13,9 +13,10 @@
$(ArtifactsFolder)\Source
$(ArtifactsFolder)\MsDeploy
$(ArtifactsFolder)\Gallery
- $(MSBuildProjectDirectory)\src\Orchard.Web\Modules
- $(MSBuildProjectDirectory)\src\Orchard.Web\Core
- $(MSBuildProjectDirectory)\src\Orchard.Web\Themes
+ $(SrcFolder)\Orchard.Web
+ $(OrchardWebFolder)\Modules
+ $(OrchardWebFolder)\Core
+ $(OrchardWebFolder)\Themes
$(BuildFolder)\Compile
$(CompileFolder)\_PublishedWebsites
@@ -112,15 +113,25 @@
+
+
+
+
+
+
+ Targets="Build"
+ Properties="Configuration=$(Configuration);MvcBuildViews=$(MvcBuildViews)" />
@@ -150,12 +161,13 @@
-
-
-
+
+
+
-
+
+
@@ -367,11 +379,6 @@
-
-
-
@@ -379,7 +386,7 @@
-
+
diff --git a/README.md b/README.md
index 45d5536883d..5a7073d2530 100644
--- a/README.md
+++ b/README.md
@@ -10,47 +10,43 @@ You can try it for free on [DotNest.com](https://dotnest.com) or on Microsoft Az
## About The Orchard Project
-#### Please visit our website at http://orchardproject.net for the most current information about this project.
+#### Please visit our website at https://orchardproject.net for the most current information about this project.
Orchard is a free, open source, community-focused **Content Management System** built on the ASP.NET MVC platform.
Orchard is built on a modern architecture that puts extensibility up-front, as its number one concern. All components in Orchard can be replaced or extended. Content is built from easily composable building blocks. Modules extend the system in a very decoupled fashion, where a commenting module for example can as easily apply to pages, blog posts, photos or products. A rich UI composition system completes the picture and ensures that you can get the exact presentation that you need for your content.
-Orchard is delivered under the [.NET Foundation](https://dotnetfoundation.org/orchard-cms). It is licensed under a [New BSD license](http://www.opensource.org/licenses/bsd-license.php), which is approved by the OSI.
+Orchard is delivered under the [.NET Foundation](https://www.dotnetfoundation.org/projects?searchquery=Orchard&type=project). It is licensed under a [New BSD license](https://www.opensource.org/licenses/bsd-license.php), which is approved by the OSI.
Our mission is to empower our users and foster a dedicated and diverse community that builds the CMS that we all want to use.
## Project Status
-Orchard is currently in version **[1.10.1](https://github.com/OrchardCMS/Orchard/releases/tag/1.10.1)**: It contains bugfixes and the more impactful changes and new features added in the latest major version (*1.10*).
+Orchard is currently in version **[1.10.3](https://github.com/OrchardCMS/Orchard/releases/tag/1.10.3)**: It contains bugfixes and the more impactful changes and new features added in the latest major version (*1.10*).
We invite participation by the developer community in shaping the project’s direction, so that we can publicly validate our designs and development approach.
-All our releases are available on our [Releases](https://github.com/OrchardCMS/Orchard/releases) page, and it's easy to [Install Orchard using the Web Platform Installer](http://docs.orchardproject.net/Documentation/Installing-Orchard) as well. We encourage interested developers to check out the source code on the Orchard GitHub site and get involved with the project.
+All our releases are available on our [Releases](https://github.com/OrchardCMS/Orchard/releases) page, and we encourage interested developers to check out the source code on the Orchard GitHub site and get involved with the project.
* [Download the latest release](https://github.com/OrchardCMS/Orchard/releases)
-* [Feature roadmap](http://docs.orchardproject.net/Documentation/Feature-roadmap)
-* [Docs and designs/specs](http://www.orchardproject.net/docs)
-* [About us](http://www.orchardproject.net/about)
-* [Contact us](mailto:ofeedbk@microsoft.com)
+* [Feature roadmap](https://docs.orchardproject.net/en/latest/Documentation/Feature-roadmap/)
+* [Docs and designs/specs](https://docs.orchardproject.net)
## How To Get Involved
We hope that by engaging with the community we will continue to shape Orchard into a valuable set of tools and applications. The Orchard team is committed to open community participation and accepts code contributions. We encourage community participation at all levels from general project feedback to bug fixes and patches.
-There are many ways you can [contribute to Orchard](http://orchardproject.net/contribution):
+There are many ways you can contribute to Orchard:
* [Check out the code](https://github.com/OrchardCMS/Orchard)
* [Write documentation](https://github.com/OrchardCMS/OrchardDoc)
* [Find and file a bug](https://github.com/OrchardCMS/Orchard/issues)
-* [Propose a feature idea](http://orchard.uservoice.com)
-* [Ask and answer questions in our forums](http://www.orchardproject.net/discussions) and [on Stack Overflow](http://stackoverflow.com/questions/tagged/orchardcms)
+* [Propose a feature idea](https://github.com/OrchardCMS/Orchard/issues/new)
+* [Ask and answer questions on Stack Overflow](https://stackoverflow.com/questions/tagged/orchardcms)
* [Participate in our gitter.im chatroom](https://gitter.im/OrchardCMS/Orchard)
-* [Participate in forum discussions](http://orchard.codeplex.com/discussions)
-* [Submit a pull request](http://docs.orchardproject.net/Documentation/Contributing-patches)
-* [Translate Orchard](http://orchardproject.net/localization)
-* [Contribute modules and themes to our gallery](http://gallery.orchardproject.net/)
-* [Send us feedback](mailto:ofeedbk@microsoft.com)
+* [Submit a pull request](https://docs.orchardproject.net/en/latest/Documentation/Contributing-patches/)
+* [Translate Orchard](https://crowdin.com/project/orchard-cms)
+* [Contribute modules and themes to our gallery](https://gallery.orchardproject.net/)
-## The Future Of Orchard CMS: Orchard 2
+## The Future Of Orchard CMS: Orchard Core
-As the underlying frameworks (.NET, ASP.NET and ASP.NET MVC) are constantly evolving, Orchard of course keeps track of the changes and improvements of these: Orchard 2 is the next generation of Orchard releases that is based on [ASP.NET Core](http://www.asp.net/core). Just like the current Orchard project, it's fully [open-source and is publicly available on GitHub](https://github.com/OrchardCMS/Orchard2). Orchard 2 (as a framework) is being built from scratch: it's still in development and does not share any of its code base (at least directly) with the current versions of Orchard.
+As the underlying frameworks (.NET, ASP.NET and ASP.NET MVC) are constantly evolving, Orchard of course keeps track of the changes and improvements of these: Orchard Core is the next generation of Orchard releases that is based on [ASP.NET Core](https://www.asp.net/core). Just like the current Orchard project, it's fully [open-source and is publicly available on GitHub](https://github.com/OrchardCMS/OrchardCore). Orchard Core (as a framework) is being built from scratch: it's still in development and does not share any of its code base (at least directly) with the current versions (1.x) of Orchard.
diff --git a/SECURITY.md b/SECURITY.md
new file mode 100644
index 00000000000..b7346a79dbb
--- /dev/null
+++ b/SECURITY.md
@@ -0,0 +1,21 @@
+# Security Policy
+
+## Supported Versions
+
+| Version | Supported |
+| ------- | ------------------ |
+| 1.0 | :x: |
+| 1.1 | :x: |
+| 1.2 | :x: |
+| 1.3 | :x: |
+| 1.4 | :x: |
+| 1.5 | :x: |
+| 1.6 | :x: |
+| 1.7 | :x: |
+| 1.8 | :x: |
+| 1.9 | :x: |
+| 1.10 | :white_check_mark: |
+
+## Reporting a Vulnerability
+
+Send an email to sebros@microsoft.com
diff --git a/deploy.ps1 b/deploy.ps1
new file mode 100644
index 00000000000..151861049e6
--- /dev/null
+++ b/deploy.ps1
@@ -0,0 +1,119 @@
+# https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/set-strictmode?view=powershell-7
+Set-StrictMode -Version Latest
+
+# https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_preference_variables?view=powershell-7#erroractionpreference
+$ErrorActionPreference = "Continue" # Just explicit set it
+
+Import-Module -Name ./DeploymentUtility -Force
+
+"Verify if Node.js installed"
+if (-not (Get-Command -Name node -ErrorAction Ignore)) {
+ throw (
+ "Missing Node.js executable, please install Node.js." +
+ "If already installed, make sure it can be reached from the current environment."
+ )
+}
+
+$ARTIFACTS = "$PSScriptRoot/../artifacts"
+# Set deployment source folder
+if (-not $Env:DEPLOYMENT_SOURCE) {
+ 'Set $DEPLOYMENT_SOURCE variable from the current directory'
+ $Env:DEPLOYMENT_SOURCE = $PSScriptRoot
+}
+
+if (-not $Env:DEPLOYMENT_TARGET) {
+ 'Set $DEPLOYMENT_TARGET variable'
+ $Env:DEPLOYMENT_TARGET = "$ARTIFACTS/wwwroot"
+}
+
+if (-not $Env:NEXT_MANIFEST_PATH) {
+ 'Set $NEXT_MANIFEST_PATH variable'
+ $Env:NEXT_MANIFEST_PATH = "$ARTIFACTS/manifest"
+
+ if (-not $Env:PREVIOUS_MANIFEST_PATH) {
+ 'Set $PREVIOUS_MANIFEST_PATH variable'
+ $Env:PREVIOUS_MANIFEST_PATH = "$ARTIFACTS/manifest"
+ }
+}
+
+# Log environment variables
+$environmentNameToWriteValue = @(
+ "DEPLOYMENT_SOURCE"
+ "DEPLOYMENT_TARGET"
+ "NEXT_MANIFEST_PATH"
+ "PREVIOUS_MANIFEST_PATH"
+ "WEBSITE_NODE_DEFAULT_VERSION"
+ "WEBSITE_NPM_DEFAULT_VERSION"
+ "SCM_REPOSITORY_PATH"
+ "SOLUTION_PATH"
+ "PROJECT_PATH"
+ "MSBUILD_PATH"
+ "Path"
+)
+Write-EnviromentValue -EnvironmentName $environmentNameToWriteValue
+
+################ Build Node.js project with yarn if there is yarn.lock file ################
+$nodeProjectsDir = Get-ChildItem -Path . -Recurse -Filter "yarn.lock" |
+ Select-Object -ExpandProperty DirectoryName -Unique |
+ Where-Object { $_ -NotMatch "node_modules" }
+
+"Node projects directory:"
+$nodeProjectsDir
+
+Install-Yarn
+
+$nodeProjectsDir | Foreach-Object {
+ $projectDir = $_
+ Push-Location -Path $projectDir
+
+ "Current Node project directory is $(Get-Location)"
+ "Installing npm packages with yarn"
+ Invoke-ExternalCommand -ScriptBlock { yarn install }
+
+ "Building Node.js project with yarn"
+ Invoke-ExternalCommand -ScriptBlock { yarn build }
+ Pop-Location
+}
+###########################################################################################
+
+# Build .NET project
+"Restore NuGet packages"
+# REF https://docs.microsoft.com/en-us/nuget/reference/cli-reference/cli-ref-restore#options
+$msBuildDir = Split-Path -Path $Env:MSBUILD_PATH -Parent
+Invoke-ExternalCommand -ScriptBlock { ./lib/nuget/nuget.exe restore "$Env:SOLUTION_PATH" -MSBuildPath "$msBuildDir" }
+
+"Build .NET project to the pre-compiled directory"
+$preCompiledDir = "$Env:DEPLOYMENT_SOURCE/build/Precompiled"
+
+"Build .NET project to the temp directory"
+"Building the project with MSBuild to '$preCompiledDir'"
+Invoke-ExternalCommand -ScriptBlock {
+ cmd /c "$Env:MSBUILD_PATH" `
+ "$Env:PROJECT_PATH" `
+ /t:Precompiled `
+ /p:PreCompiledDir=$preCompiledDir `
+ /verbosity:minimal `
+ /maxcpucount `
+ /nologo `
+ $Env:SCM_BUILD_ARGS
+ # Set SCM_BUILD_ARGS as App Service Configuration to any string you want to append to the MSBuild command line.
+}
+
+Install-KuduSync
+
+"Syncing a build output to a deployment folder"
+Invoke-ExternalCommand -ScriptBlock {
+ cmd /c kudusync `
+ -f "$preCompiledDir" `
+ -t "$Env:DEPLOYMENT_TARGET" `
+ -n "$Env:NEXT_MANIFEST_PATH" `
+ -p "$Env:PREVIOUS_MANIFEST_PATH" `
+ -i ".git;.hg;.deployment;deploy.cmd;deploy.ps1;node_modules;"
+}
+
+if ($Env:POST_DEPLOYMENT_ACTION) {
+ "Post deployment stub"
+ Invoke-ExternalCommand -ScriptBlock { $Env:POST_DEPLOYMENT_ACTION }
+}
+
+"Deployment successfully"
diff --git a/lib/nhibernate.linq/NHibernate.Linq.dll b/lib/nhibernate.linq/NHibernate.Linq.dll
deleted file mode 100644
index 4d4152a4f8a..00000000000
Binary files a/lib/nhibernate.linq/NHibernate.Linq.dll and /dev/null differ
diff --git a/lib/nhibernate.linq/orchard-customizations.txt b/lib/nhibernate.linq/orchard-customizations.txt
deleted file mode 100644
index ddb2b34c77d..00000000000
--- a/lib/nhibernate.linq/orchard-customizations.txt
+++ /dev/null
@@ -1,4 +0,0 @@
-This library has been modified to be compatible with NH 3.3.
-The file DetachedCriteriaAdapter.cs in this folder is used instead of the original onw from soure code.
-
-Source code can be found at http://sourceforge.net/projects/nhcontrib/files/NHibernate.Linq/1.0/NHibernate.Linq-1.0.0.GA-src.zip
diff --git a/lib/nuget/nuget.exe b/lib/nuget/nuget.exe
index 9f8781de0db..a6caf01c9e3 100644
Binary files a/lib/nuget/nuget.exe and b/lib/nuget/nuget.exe differ
diff --git a/lib/vswhere/vswhere.exe b/lib/vswhere/vswhere.exe
new file mode 100644
index 00000000000..80706d852e5
Binary files /dev/null and b/lib/vswhere/vswhere.exe differ
diff --git a/src/.editorconfig b/src/.editorconfig
new file mode 100644
index 00000000000..0a382f05cc7
--- /dev/null
+++ b/src/.editorconfig
@@ -0,0 +1,11 @@
+root = true
+
+[*]
+end_of_line = crlf
+indent_style = space
+indent_size = 4
+trim_trailing_whitespace = true
+
+[*.cs]
+csharp_new_line_before_open_brace = none
+dotnet_sort_system_directives_first = true
\ No newline at end of file
diff --git a/src/Gulpfile.js b/src/Gulpfile.js
index d9554f622b8..77b4df2615b 100644
--- a/src/Gulpfile.js
+++ b/src/Gulpfile.js
@@ -97,7 +97,13 @@ function resolveAssetGroupPaths(assetGroup, assetManifestPath) {
assetGroup.manifestPath = assetManifestPath;
assetGroup.basePath = path.dirname(assetManifestPath);
assetGroup.inputPaths = assetGroup.inputs.map(function (inputPath) {
- return path.resolve(path.join(assetGroup.basePath, inputPath));
+ var excludeFile = false;
+ if (inputPath.startsWith('!')) {
+ inputPath = inputPath.slice(1);
+ excludeFile = true;
+ }
+ var newPath = path.resolve(path.join(assetGroup.basePath, inputPath));
+ return (excludeFile ? '!' : '') + newPath;
});
assetGroup.watchPaths = [];
if (assetGroup.watch) {
@@ -216,7 +222,7 @@ function buildJsPipeline(assetGroup, doConcat, doRebuild) {
// Source maps are useless if neither concatenating nor transpiling.
if ((!doConcat || assetGroup.inputPaths.length < 2) && !assetGroup.inputPaths.some(function (inputPath) { return path.extname(inputPath).toLowerCase() === ".ts"; }))
generateSourceMaps = false;
- var typeScriptOptions = { allowJs: true, noImplicitAny: true, noEmitOnError: true };
+ var typeScriptOptions = { allowJs: true, noImplicitAny: true, noEmitOnError: true, module: 'amd' };
if (assetGroup.typeScriptOptions)
typeScriptOptions = Object.assign(typeScriptOptions, assetGroup.typeScriptOptions); // Merge override options from asset group if any.
if (doConcat)
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/AssemblyInfo.cs b/src/Libraries/NHibernate/NHibernate.Linq/AssemblyInfo.cs
new file mode 100644
index 00000000000..ee7696278a1
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/AssemblyInfo.cs
@@ -0,0 +1,27 @@
+using System;
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Security;
+
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:2.0.50727.4016
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+[assembly: CLSCompliantAttribute(true)]
+[assembly: AssemblyTitleAttribute("NHibernate.Linq")]
+[assembly: AssemblyDescriptionAttribute("A linq provider for NHibernate")]
+[assembly: AssemblyCompanyAttribute("NHForge.org")]
+[assembly: AssemblyProductAttribute("NHibernate.Linq")]
+[assembly: AssemblyCopyrightAttribute("Licensed under LGPL.")]
+[assembly: AssemblyVersionAttribute("1.0.0.4000")]
+[assembly: AssemblyInformationalVersionAttribute("1.0.0.4000")]
+[assembly: AssemblyFileVersionAttribute("1.0.0.4000")]
+[assembly: AssemblyDelaySignAttribute(false)]
+[assembly: AllowPartiallyTrustedCallersAttribute()]
+
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/CriteriaResultReader.cs b/src/Libraries/NHibernate/NHibernate.Linq/CriteriaResultReader.cs
new file mode 100644
index 00000000000..8337d2c1c20
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/CriteriaResultReader.cs
@@ -0,0 +1,35 @@
+using System.Collections;
+using System.Collections.Generic;
+
+namespace NHibernate.Linq
+{
+ ///
+ /// Wraps an ICriteria object providing results when necessary.
+ ///
+ ///
+ public class CriteriaResultReader : IEnumerable, IEnumerable
+ {
+ private readonly ICriteria _criteria;
+
+ public CriteriaResultReader(ICriteria criteria)
+ {
+ _criteria = criteria;
+ }
+
+ private IList List()
+ {
+ return _criteria.List();
+ }
+
+ public IEnumerator GetEnumerator()
+ {
+ foreach (var item in List())
+ yield return (T)item;
+ }
+
+ IEnumerator IEnumerable.GetEnumerator()
+ {
+ return List().GetEnumerator();
+ }
+ }
+}
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/Expressions/CollectionAccessExpression.cs b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/CollectionAccessExpression.cs
new file mode 100644
index 00000000000..ffa1e85b1fd
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/CollectionAccessExpression.cs
@@ -0,0 +1,21 @@
+using NHibernate.Type;
+
+namespace NHibernate.Linq.Expressions
+{
+ public class CollectionAccessExpression : PropertyAccessExpression
+ {
+ private readonly EntityExpression _elementExpression;
+
+ public EntityExpression ElementExpression
+ {
+ get { return _elementExpression; }
+ }
+
+ public CollectionAccessExpression(string name, System.Type type, IType nhibernateType,
+ EntityExpression expression, EntityExpression elementExpression)
+ : base(name, type, nhibernateType, expression, NHibernateExpressionType.CollectionAccess)
+ {
+ _elementExpression = elementExpression;
+ }
+ }
+}
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/Expressions/EntityExpression.cs b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/EntityExpression.cs
new file mode 100644
index 00000000000..75d4fa00cd3
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/EntityExpression.cs
@@ -0,0 +1,63 @@
+using System.Linq.Expressions;
+using NHibernate.Metadata;
+
+namespace NHibernate.Linq.Expressions
+{
+ public class EntityExpression : NHibernateExpression
+ {
+ private readonly string _alias;
+ private readonly string _associationPath;
+ private readonly IClassMetadata _metaData;
+ private readonly Expression _expression;
+
+ public string Alias
+ {
+ get { return _alias; }
+ }
+
+ public string AssociationPath
+ {
+ get { return _associationPath; }
+ }
+
+ public IClassMetadata MetaData
+ {
+ get { return _metaData; }
+ }
+
+ public Expression Expression
+ {
+ get { return _expression; }
+ }
+
+ public EntityExpression(string associationPath, string alias, System.Type type, IClassMetadata metaData, Expression expression)
+ : base(IsRoot(expression) ? NHibernateExpressionType.RootEntity : NHibernateExpressionType.Entity, type)
+ {
+ _associationPath = associationPath;
+ _alias = alias;
+ _metaData = metaData;
+ _expression = expression;
+ }
+
+ private static bool IsRoot(Expression expr)
+ {
+ if (expr == null) return true;
+ if (!(expr is EntityExpression)) return true;
+ return false;
+ }
+
+ public override string ToString()
+ {
+ return Alias;
+ }
+
+ public virtual string GetAliasedIdentifierPropertyName()
+ {
+ if ((NHibernateExpressionType)this.NodeType == NHibernateExpressionType.RootEntity)
+ {
+ return this.MetaData.IdentifierPropertyName;
+ }
+ return string.Format("{0}.{1}", this.Alias, this.MetaData.IdentifierPropertyName);
+ }
+ }
+}
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/Expressions/NHibernateExpression.cs b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/NHibernateExpression.cs
new file mode 100644
index 00000000000..ca9676e9498
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/NHibernateExpression.cs
@@ -0,0 +1,21 @@
+using System;
+using System.Linq.Expressions;
+
+namespace NHibernate.Linq.Expressions
+{
+ public abstract class NHibernateExpression : Expression
+ {
+
+ public NHibernateExpression(NHibernateExpressionType nodeType, System.Type type)
+ : base() {
+
+ _nodeType = nodeType;
+ _type = type;
+ }
+
+ private readonly NHibernateExpressionType _nodeType;
+ public override ExpressionType NodeType { get { return (ExpressionType)_nodeType; } }
+ private readonly System.Type _type;
+ public override System.Type Type { get { return _type; } }
+ }
+}
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/Expressions/NHibernateExpressionType.cs b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/NHibernateExpressionType.cs
new file mode 100644
index 00000000000..9213efc85a3
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/NHibernateExpressionType.cs
@@ -0,0 +1,15 @@
+
+namespace NHibernate.Linq.Expressions
+{
+ ///
+ /// Extended node types for custom expressions
+ ///
+ public enum NHibernateExpressionType
+ {
+ QuerySource = 1000, //make sure these don't overlap with ExpressionType
+ RootEntity,
+ Entity,
+ PropertyAccess,
+ CollectionAccess
+ }
+}
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/Expressions/PropertyAccessExpression.cs b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/PropertyAccessExpression.cs
new file mode 100644
index 00000000000..257c3d1e426
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/PropertyAccessExpression.cs
@@ -0,0 +1,48 @@
+using System;
+using NHibernate.Type;
+
+namespace NHibernate.Linq.Expressions
+{
+ public class PropertyAccessExpression : NHibernateExpression
+ {
+ private readonly string _name;
+ private readonly EntityExpression _expression;
+ private readonly IType _nhibernateType;
+
+ public string Name
+ {
+ get { return _name; }
+ }
+
+ public EntityExpression Expression
+ {
+ get { return _expression; }
+ }
+
+ public IType NHibernateType
+ {
+ get { return _nhibernateType; }
+ }
+
+ public PropertyAccessExpression(string name, System.Type type, IType nhibernateType, EntityExpression expression)
+ : this(name, type, nhibernateType, expression, NHibernateExpressionType.PropertyAccess) { }
+
+ protected PropertyAccessExpression(string name, System.Type type, IType nhibernateType, EntityExpression expression, NHibernateExpressionType nodeType)
+ : base(nodeType, type)
+ {
+ if (String.IsNullOrEmpty(name)) throw new ArgumentNullException("name");
+ if (type == null) throw new ArgumentNullException("type");
+ if (nhibernateType == null) throw new ArgumentNullException("nhibernateType");
+ if (expression == null) throw new ArgumentNullException("expression");
+
+ _name = name;
+ _expression = expression;
+ _nhibernateType = nhibernateType;
+ }
+
+ public override string ToString()
+ {
+ return this.Expression.ToString() + "." + this.Name;
+ }
+ }
+}
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/Expressions/QuerySourceExpression.cs b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/QuerySourceExpression.cs
new file mode 100644
index 00000000000..1f4f8b093ca
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/QuerySourceExpression.cs
@@ -0,0 +1,46 @@
+using System;
+using System.Linq;
+
+namespace NHibernate.Linq.Expressions
+{
+ public class QuerySourceExpression : NHibernateExpression
+ {
+ private readonly string _alias;
+ private readonly IQueryable _query;
+ private readonly System.Type _elementType;
+
+ public string Alias
+ {
+ get { return _alias; }
+ }
+
+ public IQueryable Query
+ {
+ get { return _query; }
+ }
+
+ public System.Type ElementType
+ {
+ get { return _elementType ?? Query.ElementType; }
+ }
+
+ public QuerySourceExpression(string alias, IQueryable query)
+ : this(alias, query, null) { }
+
+ public QuerySourceExpression(string alias, IQueryable query, System.Type elementType)
+ : base(NHibernateExpressionType.QuerySource, query.GetType())
+ {
+ _alias = alias;
+ _query = query;
+ _elementType = elementType;
+ }
+
+ public override string ToString()
+ {
+ if (!String.IsNullOrEmpty(Alias))
+ return Alias;
+
+ return base.ToString();
+ }
+ }
+}
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/Expressions/SqlAggregateFunctionProjection.cs b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/SqlAggregateFunctionProjection.cs
new file mode 100644
index 00000000000..7945c86c4de
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/SqlAggregateFunctionProjection.cs
@@ -0,0 +1,88 @@
+using System;
+using System.Collections.Generic;
+using NHibernate.Criterion;
+using NHibernate.Linq.Util;
+using NHibernate.SqlCommand;
+using NHibernate.Type;
+
+namespace NHibernate.Linq.Expressions
+{
+ public class SqlAggregateFunctionProjection : AggregateProjection
+ {
+ public SqlAggregateFunctionProjection(string functionName, string propertyName)
+ : this(functionName, propertyName, null)
+ {
+ }
+
+ public SqlAggregateFunctionProjection(string functionName, string propertyName, System.Type returnType)
+ : this(functionName, propertyName, returnType, null)
+ {
+ }
+
+ public SqlAggregateFunctionProjection(string functionName, string propertyName, System.Type returnType, object[] paramValues)
+ : this(functionName, propertyName, 0, returnType, paramValues)
+ {
+ }
+
+ public SqlAggregateFunctionProjection(string functionName, string propertyName, int propertyPosition, System.Type returnType,
+ object[] paramValues)
+ : base(functionName, propertyName)
+ {
+ ReturnType = returnType;
+ ParameterValues = paramValues;
+ PropertyPosition = propertyPosition;
+ }
+
+ public System.Type ReturnType { get; private set; }
+ public Object[] ParameterValues { get; private set; }
+ public int PropertyPosition { get; private set; }
+
+ public override IType[] GetTypes(ICriteria criteria, ICriteriaQuery criteriaQuery)
+ {
+ if (ReturnType != null)
+ {
+ return new[] { TypeFactory.HeuristicType(ReturnType.Name) };
+ }
+
+ return base.GetTypes(criteria, criteriaQuery);
+ }
+
+ public override SqlString ToSqlString(ICriteria criteria, int loc, ICriteriaQuery criteriaQuery)
+ {
+ if (ParameterValues != null && ParameterValues.Length > 0)
+ {
+ var sql = new SqlStringBuilder();
+ sql.Add(aggregate).Add("(");
+ bool hasProperty = false;
+ bool hasParameter = false;
+
+ for (int i = 0; i < ParameterValues.Length; i++)
+ {
+ if (PropertyPosition == i)
+ {
+ if (i > 0) sql.Add(", ");
+ sql.Add(criteriaQuery.GetColumn(criteria, propertyName)).Add(", ");
+ hasProperty = true;
+ }
+ else if (i > 0)
+ {
+ sql.Add(", ");
+ }
+
+ sql.Add(LinqUtil.SqlEncode(ParameterValues[i]));
+ hasParameter = true;
+ }
+ if (!hasProperty)
+ {
+ if (hasParameter) sql.Add(", ");
+ sql.Add(criteriaQuery.GetColumn(criteria, propertyName));
+ }
+
+ return sql.Add(") as y").Add(loc.ToString()).Add("_").ToSqlString();
+ }
+
+ // if ParameterValues were not specified, we defer to the base functionality
+ return base.ToSqlString(criteria, loc, criteriaQuery);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/Expressions/SqlFunctionAttribute.cs b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/SqlFunctionAttribute.cs
new file mode 100644
index 00000000000..a51a60d9810
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/SqlFunctionAttribute.cs
@@ -0,0 +1,37 @@
+using System;
+
+namespace NHibernate.Linq.Expressions
+{
+ ///
+ /// Associates a method with a corresponding SQL function.
+ ///
+ [AttributeUsage(AttributeTargets.Method, Inherited = false, AllowMultiple = false)]
+ public class SqlFunctionAttribute : Attribute
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public SqlFunctionAttribute()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The name of the schema that owns the SQL function.
+ public SqlFunctionAttribute(string owner)
+ {
+ Owner = owner;
+ }
+
+ ///
+ /// Gets or sets the name of the schema that owns the SQL function.
+ ///
+ public string Owner { get; set; }
+
+ ///
+ /// Gets or sets the position of the function parameter that accepts the property name.
+ ///
+ public int PropertyPosition { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/Expressions/SqlFunctionExpression.cs b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/SqlFunctionExpression.cs
new file mode 100644
index 00000000000..fcc53c9efbf
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/Expressions/SqlFunctionExpression.cs
@@ -0,0 +1,170 @@
+using System;
+using System.Collections.Generic;
+using System.Reflection;
+using NHibernate.Criterion;
+using NHibernate.Engine;
+using NHibernate.SqlCommand;
+using NHibernate.Type;
+
+namespace NHibernate.Linq.Expressions
+{
+ public class SqlFunctionExpression : ICriterion
+ {
+ private String op;
+
+ public SqlFunctionExpression(String functionName, System.Type returnType, ICriterion innerCriterion)
+ : this(functionName, returnType, null, null, innerCriterion, 0, null)
+ {
+ }
+
+ public SqlFunctionExpression(String functionName, System.Type returnType, Object[] paramValues,
+ System.Type[] paramTypes, ICriterion innerCriterion)
+ : this(functionName, returnType, paramValues, paramTypes, innerCriterion, 0, null)
+ {
+ }
+
+ public SqlFunctionExpression(String functionName, System.Type returnType, Object[] paramValues,
+ System.Type[] paramTypes, ICriterion innerCriterion, int propertyPosition)
+ : this(functionName, returnType, paramValues, paramTypes, innerCriterion, propertyPosition, null)
+ {
+ }
+
+ public SqlFunctionExpression(String functionName, System.Type returnType, Object[] paramValues,
+ System.Type[] paramTypes, ICriterion innerCriterion, int propertyPosition,
+ SqlFunctionExpression rightFunction)
+ {
+ FunctionName = functionName;
+ ReturnType = returnType;
+ ParameterValues = paramValues;
+ ParameterTypes = paramTypes;
+ InnerCriterion = innerCriterion;
+ PropertyPosition = propertyPosition;
+ RightFunction = rightFunction;
+ }
+
+ private SqlFunctionExpression RightFunction { get; set; }
+ public ICriterion InnerCriterion { get; set; }
+ public String FunctionName { get; private set; }
+ public System.Type ReturnType { get; private set; }
+ public Object[] ParameterValues { get; private set; }
+ public System.Type[] ParameterTypes { get; private set; }
+ public int PropertyPosition { get; private set; }
+
+ protected virtual string Op
+ {
+ get
+ {
+ if (String.IsNullOrEmpty(op))
+ {
+ op = InnerCriterion.GetType().GetProperty("Op", BindingFlags.NonPublic | BindingFlags.Instance)
+ .GetValue(InnerCriterion, null) as String;
+ }
+
+ return op;
+ }
+ }
+
+ #region ICriterion Members
+
+ public virtual TypedValue[] GetTypedValues(ICriteria criteria, ICriteriaQuery criteriaQuery)
+ {
+ var values = new List();
+ if (ParameterValues != null)
+ {
+ for (int i = 0; i < ParameterValues.Length; i++)
+ {
+ values.Add(new TypedValue(TypeFactory.HeuristicType(ParameterTypes[i].Name), ParameterValues[i]));
+ }
+ }
+ if (ReturnType != null && InnerCriterion is SimpleExpression)
+ {
+ var simple = InnerCriterion as SimpleExpression;
+ values.Add(new TypedValue(TypeFactory.HeuristicType(ReturnType.Name), simple.Value));
+ }
+ if (RightFunction != null)
+ {
+ values.AddRange(RightFunction.GetTypedValues(criteria, criteriaQuery));
+ }
+
+ return values.ToArray();
+ }
+
+ public virtual SqlString ToSqlString(ICriteria criteria, ICriteriaQuery criteriaQuery)
+ {
+ var sql = new SqlStringBuilder();
+ string leftPropertyName = null;
+ string rightPropertyName = null;
+
+ if (InnerCriterion is SimpleExpression)
+ {
+ leftPropertyName = ((SimpleExpression)InnerCriterion).PropertyName;
+ }
+ else if (InnerCriterion is PropertyExpression)
+ {
+ System.Type type = typeof(PropertyExpression);
+ leftPropertyName =
+ type.GetField("_lhsPropertyName", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(InnerCriterion) as
+ String;
+ rightPropertyName =
+ type.GetField("_rhsPropertyName", BindingFlags.NonPublic | BindingFlags.Instance).GetValue(InnerCriterion) as
+ String;
+ }
+
+ AddParameters(leftPropertyName, sql, criteria, criteriaQuery);
+ sql.Add(" ").Add(Op).Add(" ");
+
+ if (RightFunction != null)
+ {
+ RightFunction.AddParameters(rightPropertyName, sql, criteria, criteriaQuery);
+ }
+ else
+ {
+ sql.AddParameter();
+ }
+
+ return sql.ToSqlString();
+ }
+
+ public IProjection[] GetProjections()
+ {
+ return null;
+ }
+
+ #endregion
+
+ private void AddParameters(String propertyName, SqlStringBuilder sql, ICriteria criteria, ICriteriaQuery criteriaQuery)
+ {
+ bool hasProperty = false;
+ bool hasParameter = false;
+
+ sql.Add(FunctionName).Add("(");
+
+ if (ParameterValues != null && ParameterValues.Length > 0)
+ {
+ for (int i = 0; i < ParameterValues.Length; i++)
+ {
+ if (PropertyPosition == i)
+ {
+ if (i > 0) sql.Add(", ");
+ sql.Add(criteriaQuery.GetColumn(criteria, propertyName)).Add(", ");
+ hasProperty = true;
+ }
+ else if (i > 0)
+ {
+ sql.Add(", ");
+ }
+
+ sql.AddParameter();
+ hasParameter = true;
+ }
+ }
+ if (!hasProperty)
+ {
+ if (hasParameter) sql.Add(", ");
+ sql.Add(criteriaQuery.GetColumn(criteria, propertyName));
+ }
+
+ sql.Add(")");
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/IDbMethods.cs b/src/Libraries/NHibernate/NHibernate.Linq/IDbMethods.cs
new file mode 100644
index 00000000000..a8af4d2fcff
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/IDbMethods.cs
@@ -0,0 +1,9 @@
+namespace NHibernate.Linq
+{
+ ///
+ /// Marker interface used to conditionally include database provider specific methods.
+ ///
+ public interface IDbMethods
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/INHibernateQueryable.cs b/src/Libraries/NHibernate/NHibernate.Linq/INHibernateQueryable.cs
new file mode 100644
index 00000000000..470d821bbd8
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/INHibernateQueryable.cs
@@ -0,0 +1,14 @@
+using System.Linq;
+
+namespace NHibernate.Linq
+{
+ public interface INHibernateQueryable
+ {
+ QueryOptions QueryOptions { get; }
+ }
+
+ public interface INHibernateQueryable : INHibernateQueryable, IOrderedQueryable
+ {
+ IQueryable Expand(string path);
+ }
+}
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/NHibernate.Linq.build b/src/Libraries/NHibernate/NHibernate.Linq/NHibernate.Linq.build
new file mode 100644
index 00000000000..7b6021d46e9
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/NHibernate.Linq.build
@@ -0,0 +1,46 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/NHibernate.Linq.csproj b/src/Libraries/NHibernate/NHibernate.Linq/NHibernate.Linq.csproj
new file mode 100644
index 00000000000..46467801f78
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/NHibernate.Linq.csproj
@@ -0,0 +1,139 @@
+
+
+ Debug
+ AnyCPU
+ 9.0.30729
+ 2.0
+ {2CF9A83A-BC40-4485-A763-BFF59B2EBDAD}
+ Library
+ Properties
+ NHibernate.Linq
+ NHibernate.Linq
+ v4.8
+ 512
+
+
+ false
+ ..\NH.Linq.snk
+
+
+
+
+ 3.5
+
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG
+ prompt
+ 4
+ false
+
+
+ none
+ true
+ bin\Release\
+ TRACE;USING_NET_35_SP1
+ prompt
+ 4
+ false
+
+
+
+ ..\..\..\packages\Antlr3.Runtime.3.5.1\lib\net40-client\Antlr3.Runtime.dll
+
+
+ ..\..\..\packages\Iesi.Collections.4.0.4\lib\net461\Iesi.Collections.dll
+
+
+
+ ..\..\..\packages\NHibernate.5.3.10\lib\net461\NHibernate.dll
+
+
+ ..\..\..\packages\Remotion.Linq.2.2.0\lib\net45\Remotion.Linq.dll
+
+
+ ..\..\..\packages\Remotion.Linq.EagerFetching.2.2.0\lib\net45\Remotion.Linq.EagerFetching.dll
+
+
+
+
+ 3.5
+
+
+
+ 3.5
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Libraries/NHibernate/NHibernate.Linq/NHibernateContext.cs b/src/Libraries/NHibernate/NHibernate.Linq/NHibernateContext.cs
new file mode 100644
index 00000000000..51d6a4d81f4
--- /dev/null
+++ b/src/Libraries/NHibernate/NHibernate.Linq/NHibernateContext.cs
@@ -0,0 +1,432 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Data.Services;
+using System.Linq;
+using System.Reflection;
+using NHibernate.Metadata;
+
+namespace NHibernate.Linq
+{
+ ///
+ /// Wraps an object to provide base functionality
+ /// for custom, database-specific context classes.
+ ///
+ public abstract class NHibernateContext : IDisposable, ICloneable, IUpdatable, IExpandProvider
+ {
+ ///
+ /// Provides access to database provider specific methods.
+ ///
+ public readonly IDbMethods Methods;
+
+ private ISession session;
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public NHibernateContext()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// An initialized object.
+ public NHibernateContext(ISession session)
+ {
+ this.session = session;
+ }
+
+ ///
+ /// Gets a reference to the associated with this object.
+ ///
+ public virtual ISession Session
+ {
+ get
+ {
+ if (session == null)
+ {
+ // Attempt to get the Session
+ session = ProvideSession();
+ }
+ return session;
+ }
+ }
+
+
+
+ ///
+ /// Allows for empty construction but provides an interface for an interface to have the derived
+ /// classes provide a session object late in the cycle.
+ ///
+ /// The Required object.
+ protected virtual ISession ProvideSession()
+ {
+ // Should not be called as supplying the session in the constructor
+ throw new NotImplementedException("If NHibernateContext is constructed with the empty constructor, inheritor is required to override ProvideSession to supply Session.");
+ }
+
+ #region ICloneable Members
+
+ ///
+ /// Creates a new object that is a copy of the current instance.
+ ///
+ ///
+ public virtual object Clone()
+ {
+ if (session == null)
+ {
+ throw new ArgumentNullException("session");
+ }
+
+ return Activator.CreateInstance(GetType(), session);
+ }
+
+ #endregion
+
+ #region IDisposable Members
+
+ ///
+ /// Disposes the wrapped object.
+ ///
+ public virtual void Dispose()
+ {
+ if (session != null)
+ {
+ session.Dispose();
+ session = null;
+ }
+ }
+
+ #endregion
+
+ #region IUpdatable Members
+
+ List