├── docs
└── example.png
├── .gitattributes
├── package.json
├── SitecoreQL
├── App_Config
│ └── Include
│ │ ├── z.SitecoreQL
│ │ └── SitecoreQL.DependencyConfigurator.config
│ │ └── z.Jabberwocky
│ │ ├── 1.Jabberwocky.DependencyInjection.Sc.config
│ │ └── 1.Jabberwocky.WebApi.Sc.config
├── Types
│ ├── KeyValuePairType.cs
│ ├── SortDirectionGraphType.cs
│ ├── ItemArrayType.cs
│ ├── ItemPathType.cs
│ ├── ItemStatisticsType.cs
│ ├── SearchQueryType.cs
│ ├── FilterGraphType.cs
│ ├── SortGraphType.cs
│ ├── ItemType.cs
│ └── SearchItemType.cs
├── Schema
│ └── SitecoreSchema.cs
├── Converters
│ ├── IArgumentToExpressionConverter.cs
│ └── ArgumentToExpressionConverter.cs
├── Web.Debug.config
├── Web.Release.config
├── Controllers
│ └── SitecoreQLController.cs
├── Properties
│ └── AssemblyInfo.cs
├── App_Start
│ └── DependencyConfigurator.cs
├── Web.config
├── Repositories
│ └── IReadOnlyRepository.cs
├── Query
│ └── ItemQuery.cs
├── packages.config
├── SitecoreQL.html
├── SitecoreQL.csproj
└── assets
│ └── graphiql.css
├── SitecoreQL.sln
├── README.md
└── .gitignore
/docs/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kmazzoni/SitecoreQL/HEAD/docs/example.png
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | # Do not adjust line endings on Sitecore .item files
5 | *.item -text
6 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "description": "An example using SitecoreQL",
3 | "scripts": {},
4 | "dependencies": {
5 | "graphiql": "^0.11.3"
6 | },
7 | "optionalDependencies": {}
8 | }
9 |
--------------------------------------------------------------------------------
/SitecoreQL/App_Config/Include/z.SitecoreQL/SitecoreQL.DependencyConfigurator.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/SitecoreQL/Types/KeyValuePairType.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using GraphQL.Types;
3 |
4 | namespace SitecoreQL.Types
5 | {
6 | public class KeyValuePairType : ObjectGraphType>
7 | {
8 | public KeyValuePairType()
9 | {
10 | Field(x => x.Key);
11 | Field(x => x.Value);
12 | }
13 | }
14 | }
--------------------------------------------------------------------------------
/SitecoreQL/Schema/SitecoreSchema.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using GraphQL.Types;
3 | using SitecoreQL.Query;
4 |
5 | namespace SitecoreQL.Schema
6 | {
7 | public class SitecoreSchema : GraphQL.Types.Schema
8 | {
9 | public SitecoreSchema(Func resolveType)
10 | : base(resolveType)
11 | {
12 | Query = (ItemQuery)resolveType(typeof(ItemQuery));
13 | }
14 | }
15 | }
--------------------------------------------------------------------------------
/SitecoreQL/Types/SortDirectionGraphType.cs:
--------------------------------------------------------------------------------
1 | using GraphQL.Types;
2 |
3 | namespace SitecoreQL.Types
4 | {
5 | public class SortDirectionGraphType : EnumerationGraphType
6 | {
7 | public SortDirectionGraphType()
8 | {
9 | Name = "SortDirection";
10 | Description = "Direction to sort results (asc/desc)";
11 | AddValue("ASC", "Ascending", 1);
12 | AddValue("DESC", "Descending", 2);
13 | }
14 | }
15 |
16 | public enum SortDirection
17 | {
18 | ASC = 1,
19 | DESC = 2
20 | }
21 | }
--------------------------------------------------------------------------------
/SitecoreQL/Types/ItemArrayType.cs:
--------------------------------------------------------------------------------
1 | using GraphQL.Types;
2 | using Sitecore.Data.Items;
3 |
4 | namespace SitecoreQL.Types
5 | {
6 | public class ItemArrayType : ObjectGraphType-
7 | {
8 | public ItemArrayType()
9 | {
10 | Name = "ItemArray";
11 |
12 | Field("count", "The number of items returned from the xpath query.", resolve: context => context.Source.Length);
13 | Field>("items", "The items matching the xpath query.", resolve: context => context.Source);
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/SitecoreQL/App_Config/Include/z.Jabberwocky/1.Jabberwocky.DependencyInjection.Sc.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/SitecoreQL/Types/ItemPathType.cs:
--------------------------------------------------------------------------------
1 | using GraphQL.Types;
2 | using Sitecore.Data;
3 |
4 | namespace SitecoreQL.Types
5 | {
6 | public class ItemPathType : ObjectGraphType
7 | {
8 | public ItemPathType()
9 | {
10 | Name = "ItemPath";
11 |
12 | Field(x => x.ContentPath);
13 | Field(x => x.FullPath);
14 | Field(x => x.IsContentItem);
15 | Field(x => x.IsFullyQualified);
16 | Field(x => x.IsMasterPart);
17 | Field(x => x.IsMediaItem);
18 | Field(x => x.MediaPath);
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/SitecoreQL/Types/ItemStatisticsType.cs:
--------------------------------------------------------------------------------
1 | using GraphQL.Types;
2 | using Sitecore.Data.Items;
3 |
4 | namespace SitecoreQL.Types
5 | {
6 | public class ItemStatisticsType : ObjectGraphType
7 | {
8 | public ItemStatisticsType()
9 | {
10 | Field(x => x.Created, true).Description("The date the item was created.");
11 | Field(x => x.CreatedBy, true).Description("The username of the person who created the item.");
12 | Field(x => x.Updated, true).Description("The date the item was last updated.");
13 | Field(x => x.UpdatedBy, true).Description("The username of the person who last updated the item.");
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/SitecoreQL/Converters/IArgumentToExpressionConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 | using SitecoreQL.Query;
6 |
7 | namespace SitecoreQL.Converters
8 | {
9 | public interface IArgumentToExpressionConverter
10 | {
11 | Expression> ConvertToFilter(IDictionary arguments);
12 | Func, IOrderedQueryable> ConvertToOrderBy(IDictionary arguments);
13 | IEnumerable>> ConvertToFacets(IEnumerable arguments);
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/SitecoreQL/App_Config/Include/z.Jabberwocky/1.Jabberwocky.WebApi.Sc.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/SitecoreQL/Types/SearchQueryType.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using GraphQL.Types;
3 | using Sitecore.ContentSearch.Linq;
4 | using SitecoreQL.Query;
5 |
6 | namespace SitecoreQL.Types
7 | {
8 | public class SearchQueryType : ObjectGraphType>
9 | {
10 | public SearchQueryType()
11 | {
12 | Name = "SearchQueryResult";
13 | Description = "Search results.";
14 |
15 | Field(x => x.TotalSearchResults).Name("totalCount").Description("Total number of items matching the search criteria.");
16 | Field>("items", "The items returned from the search.", resolve: context =>
17 | {
18 | return context.Source.Select(x => x.Document);
19 | });
20 | Field>("facets", "The set of requested facets and their values/counts.", resolve: context => context.Source.Facets.Categories);
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/SitecoreQL.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.24720.0
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SitecoreQL", "SitecoreQL\SitecoreQL.csproj", "{1561109E-2D00-46AB-9D95-5E60347F4C07}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {1561109E-2D00-46AB-9D95-5E60347F4C07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {1561109E-2D00-46AB-9D95-5E60347F4C07}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {1561109E-2D00-46AB-9D95-5E60347F4C07}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {1561109E-2D00-46AB-9D95-5E60347F4C07}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SitecoreQL
2 | GraphQL implementation for Sitecore.
3 |
4 | Query against Sitecore's Content Search API:
5 |
6 | 
7 |
8 | ## Getting Started
9 |
10 | Want to play around?
11 |
12 | 1. Fork this repo
13 | 2. Install an instance of Sitecore 8.2 ([Use SIM!](https://github.com/Sitecore/Sitecore-Instance-Manager))
14 | 3. Open Visual Studio and publish the SitecoreQL project to your Sitecore instance.
15 | 4. Load SitecoreQL.html in your browser and test it out.
16 |
17 | ## GraphQL
18 | [GraphQL](http://graphql.org/) is a query language for APIs and a runtime for fulfilling those queries with your existing data. GraphQL provides a complete and understandable description of the data in your API, gives clients the power to ask for exactly what they need and nothing more, makes it easier to evolve APIs over time, and enables powerful developer tools.
19 |
20 | ## GraphQL for .NET
21 | Facebook's GraphQL implementation for .NET. [https://github.com/graphql-dotnet/graphql-dotnet](https://github.com/graphql-dotnet/graphql-dotnet)
22 |
--------------------------------------------------------------------------------
/SitecoreQL/Types/FilterGraphType.cs:
--------------------------------------------------------------------------------
1 | using GraphQL.Types;
2 |
3 | namespace SitecoreQL.Types
4 | {
5 | public class FilterGraphType : InputObjectGraphType
6 | {
7 | public FilterGraphType()
8 | {
9 | Name = "Filter";
10 |
11 | Field("id", "The item's unique ID.");
12 | Field("name", "The name of the item.");
13 | Field("language", "The language the item was created in.");
14 | Field("databaseName", "The name of the database the item was searched from.");
15 | Field("templateId", "The ID of the item's template.");
16 | Field("templateName", "The name of the item's template.");
17 | Field("parentId", "The ID of the item's parent.");
18 | Field("createdBy", "The username of the person who created the item.");
19 | Field("updatedBy", "The username of the person who last updated the item.");
20 | Field("isLatestVersion", "True/False whether this is the latest version of the item.");
21 | Field("site", "The name of the site the item belongs to.");
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/SitecoreQL/Web.Debug.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
29 |
30 |
--------------------------------------------------------------------------------
/SitecoreQL/Types/SortGraphType.cs:
--------------------------------------------------------------------------------
1 | using GraphQL.Types;
2 | using Sitecore.ContentSearch.Linq;
3 |
4 | namespace SitecoreQL.Types
5 | {
6 | public class SortGraphType : InputObjectGraphType
7 | {
8 | public SortGraphType()
9 | {
10 | Name = "Sort";
11 | Description = "Specify the field to sort on and direction.";
12 | Field("field", "The Sitecore field to sort all results by.");
13 | Field("dir", "The direction the results should be ordered by (ASC/DESC).");
14 | }
15 | }
16 |
17 | public class FacetsGraphType : ObjectGraphType
18 | {
19 | public FacetsGraphType()
20 | {
21 | Name = "Facets";
22 |
23 | Field(x => x.Name).Description("The facet's name.");
24 | Field(x => x.Values, type:typeof(ListGraphType)).Description("The valid values for this facet.");
25 | }
26 | }
27 |
28 | public class FacetValueGraphType : ObjectGraphType
29 | {
30 | public FacetValueGraphType()
31 | {
32 | Name = "FacetValues";
33 |
34 | Field(x => x.Name).Description("The facet value's name.");
35 | Field(x => x.AggregateCount).Name("count").Description("The number of item's whose field value matches this facet value's name.");
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/SitecoreQL/Web.Release.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
19 |
30 |
31 |
--------------------------------------------------------------------------------
/SitecoreQL/Controllers/SitecoreQLController.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using System.Threading.Tasks;
3 | using System.Web.Http;
4 | using System.Web.Http.Results;
5 | using GraphQL;
6 | using GraphQL.Types;
7 | using Newtonsoft.Json;
8 |
9 | namespace SitecoreQL.Controllers
10 | {
11 | public class SitecoreQLController : ApiController
12 | {
13 | private readonly ISchema _schema;
14 | private readonly IDocumentExecuter _executer;
15 |
16 | public SitecoreQLController(IDocumentExecuter executer,
17 | ISchema schema)
18 | {
19 | _executer = executer;
20 | _schema = schema;
21 | }
22 |
23 | [HttpPost]
24 | public async Task Post(GraphQlModel query)
25 | {
26 | var result = await _executer.ExecuteAsync(_ =>
27 | {
28 | _.Schema = _schema;
29 | _.Query = query.Query;
30 | _.OperationName = query.OperationName ?? string.Empty;
31 | _.Inputs = query.Variables.ToInputs();
32 | });
33 |
34 | return new JsonResult(result, new JsonSerializerSettings(), Encoding.UTF8, this);
35 | }
36 | }
37 |
38 | public class GraphQlModel
39 | {
40 | public string OperationName { get; set; }
41 | public string NamedQuery { get; set; }
42 | public string Query { get; set; }
43 | public string Variables { get; set; }
44 | }
45 | }
--------------------------------------------------------------------------------
/SitecoreQL/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | using System.Reflection;
2 | using System.Runtime.CompilerServices;
3 | using System.Runtime.InteropServices;
4 |
5 | // General Information about an assembly is controlled through the following
6 | // set of attributes. Change these attribute values to modify the information
7 | // associated with an assembly.
8 | [assembly: AssemblyTitle("SitecoreQL")]
9 | [assembly: AssemblyDescription("")]
10 | [assembly: AssemblyConfiguration("")]
11 | [assembly: AssemblyCompany("")]
12 | [assembly: AssemblyProduct("SitecoreQL")]
13 | [assembly: AssemblyCopyright("Copyright © 2017")]
14 | [assembly: AssemblyTrademark("")]
15 | [assembly: AssemblyCulture("")]
16 |
17 | // Setting ComVisible to false makes the types in this assembly not visible
18 | // to COM components. If you need to access a type in this assembly from
19 | // COM, set the ComVisible attribute to true on that type.
20 | [assembly: ComVisible(false)]
21 |
22 | // The following GUID is for the ID of the typelib if this project is exposed to COM
23 | [assembly: Guid("1561109e-2d00-46ab-9d95-5e60347f4c07")]
24 |
25 | // Version information for an assembly consists of the following four values:
26 | //
27 | // Major Version
28 | // Minor Version
29 | // Build Number
30 | // Revision
31 | //
32 | // You can specify all the values or you can default the Revision and Build Numbers
33 | // by using the '*' as shown below:
34 | [assembly: AssemblyVersion("1.0.0.0")]
35 | [assembly: AssemblyFileVersion("1.0.0.0")]
36 |
--------------------------------------------------------------------------------
/SitecoreQL/App_Start/DependencyConfigurator.cs:
--------------------------------------------------------------------------------
1 | using GraphQL;
2 | using GraphQL.Types;
3 | using Microsoft.Extensions.DependencyInjection;
4 | using Sitecore.DependencyInjection;
5 | using SitecoreQL.Controllers;
6 | using SitecoreQL.Converters;
7 | using SitecoreQL.Query;
8 | using SitecoreQL.Repositories;
9 | using SitecoreQL.Schema;
10 | using SitecoreQL.Types;
11 |
12 | namespace SitecoreQL.App_Start
13 | {
14 | public class DependencyConfigurator : IServicesConfigurator
15 | {
16 | public void Configure(IServiceCollection serviceCollection)
17 | {
18 | serviceCollection.AddSingleton();
19 | serviceCollection.AddTransient();
20 | serviceCollection.AddTransient();
21 | serviceCollection.AddTransient();
22 | serviceCollection.AddTransient();
23 | serviceCollection.AddTransient();
24 | serviceCollection.AddTransient();
25 | serviceCollection.AddTransient();
26 | serviceCollection.AddTransient();
27 | serviceCollection.AddTransient();
28 | serviceCollection.AddTransient();
29 | serviceCollection.AddTransient();
30 | serviceCollection.AddTransient();
31 | serviceCollection.AddTransient();
32 | serviceCollection.AddTransient, ItemRepository>();
33 | serviceCollection.AddTransient();
34 | serviceCollection.AddTransient(d => new SitecoreSchema(type => (GraphType)d.GetService(type)));
35 | serviceCollection.AddTransient();
36 | }
37 | }
38 | }
--------------------------------------------------------------------------------
/SitecoreQL/Types/ItemType.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using GraphQL.Types;
5 | using Sitecore.Data.Items;
6 | using Sitecore.Links;
7 |
8 | namespace SitecoreQL.Types
9 | {
10 | public class ItemType : ObjectGraphType
-
11 | {
12 | public ItemType()
13 | {
14 | Name = "SitecoreItem";
15 | Description = "Sitecore item.";
16 |
17 | Field("id", "The item's unique ID.", resolve: context => context?.Source?.ID?.Guid.ToString() ?? Guid.Empty.ToString());
18 | Field(x => x.Name).Description("The name of the item.");
19 | Field("language", "The language the item was created in.", resolve: context => context.Source.Language.Name);
20 | Field("database", "The name of the database the item was searched from.", resolve: context => context.Source.Database.Name);
21 | Field("paths", "The Sitecore item path.");
22 | Field("url", "The item's relative URL.", resolve: context => LinkManager.GetItemUrl(context.Source));
23 | Field("version", "The version number of the item", resolve: context => context.Source.Version.Number);
24 | Field>("fields", "The item's custom fields.", resolve: context =>
25 | {
26 | return context.Source?.Fields?.Select(f => new KeyValuePair(f.Key, f.Value as string)) ?? Enumerable.Empty>();
27 | });
28 | Field("template", "The template of the item.", resolve: context => context.Source.Template.InnerItem);
29 | Field("parent", "The item's parent.", resolve: context => context.Source.Parent);
30 | Field>("children", "The direction children of the item.", resolve: context => context.Source.Children.ToArray());
31 | Field("statistics", "The Sitecore item statistics.");
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/SitecoreQL/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/SitecoreQL/Types/SearchItemType.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using GraphQL.Types;
5 | using SitecoreQL.Query;
6 | using SitecoreQL.Repositories;
7 |
8 | namespace SitecoreQL.Types
9 | {
10 | public class SearchItemType : ObjectGraphType
11 | {
12 | public SearchItemType(IReadOnlyRepository repo)
13 | {
14 | Name = "SearchResultItem";
15 | Description = "Sitecore item.";
16 |
17 | Field("id", "The item's unique ID.", resolve: context => context?.Source?.ItemId?.Guid.ToString() ?? Guid.Empty.ToString());
18 | Field(x => x.Name, true).Description("The name of the item.");
19 | Field(x => x.Language, true).Description("The language the item was created in.");
20 | Field(x => x.DatabaseName, true).Description("The name of the database the item was searched from.");
21 | Field(x => x.Path, true).Description("The Sitecore item path.");
22 | Field(x => x.Url, true).Description("The item's relative URL.");
23 | Field(x => x.CreatedDate, true).Description("The date the item was created.");
24 | Field(x => x.CreatedBy, true).Description("The username of the person who created the item.");
25 | Field(x => x.Updated, true).Description("The date the item was last updated.");
26 | Field(x => x.UpdatedBy, true).Description("The username of the person who last updated the item.");
27 | Field(x => x.Version, true).Description("The version number of the item");
28 |
29 | var fieldArguments = new QueryArguments
30 | {
31 | new QueryArgument> { Name = "keys", DefaultValue = new string[] { }}
32 | };
33 | Field>("fields", "The item's custom fields.", fieldArguments, context =>
34 | {
35 | var keys = context.GetArgument>("keys");
36 | return context.Source?.Fields?.Where(f => !keys.Any() || keys.Contains(f.Key)).Select(f => new KeyValuePair(f.Key, f.Value as string)) ?? Enumerable.Empty>();
37 | });
38 | Field("template", "The template of the item.", resolve: context => repo.GetById(context.Source.TemplateId.Guid));
39 | Field("parent", "The item's parent.", resolve: context => repo.GetById(context.Source.Parent.Guid));
40 | Field>("children", "The direction children of the item.", resolve: context => repo.GetMany(x => x.Parent == context.Source.ItemId).Select(h => h.Document));
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | __MACOSX
2 | node_modules
3 | npm-debug.log
4 | .idea
5 | .DS_Store
6 | Thumbs.db
7 | .sass-cache
8 |
9 | # Build Folders (you can keep bin if you'd like, to store dlls and pdbs)
10 | [Bb]in/
11 | [Oo]bj/
12 |
13 | # mstest test results
14 | TestResults
15 |
16 | ## Ignore Visual Studio temporary files, build results, and
17 | ## files generated by popular Visual Studio add-ons.
18 |
19 | # User-specific files
20 | *.suo
21 | *.user
22 | *.sln.docstates
23 | .vs
24 |
25 | # Build results
26 | [Dd]ebug/
27 | [Rr]elease/
28 | x64/
29 | *_i.c
30 | *_p.c
31 | *.ilk
32 | *.meta
33 | *.obj
34 | *.pch
35 | *.pdb
36 | *.pgc
37 | *.pgd
38 | *.rsp
39 | *.sbr
40 | *.tlb
41 | *.tli
42 | *.tlh
43 | *.tmp
44 | *.log
45 | *.vspscc
46 | *.vssscc
47 | .builds
48 |
49 | # Visual C++ cache files
50 | ipch/
51 | *.aps
52 | *.ncb
53 | *.opensdf
54 | *.sdf
55 |
56 | # Visual Studio profiler
57 | *.psess
58 | *.vsp
59 | *.vspx
60 |
61 | # Visual Studio IDE settings
62 | *.sln.ide/
63 |
64 | # Visual Studio Web Service References
65 | *.svcinfo
66 | *.disco
67 | *.xsd
68 | *.wsdl
69 | *.datasource
70 |
71 | # Guidance Automation Toolkit
72 | *.gpState
73 |
74 | # ReSharper is a .NET coding add-in
75 | _ReSharper*
76 |
77 | # NCrunch
78 | *.ncrunch*
79 | .*crunch*.local.xml
80 | *_NCrunch_*
81 |
82 | # Installshield output folder
83 | [Ee]xpress
84 |
85 | # DocProject is a documentation generator add-in
86 | DocProject/buildhelp/
87 | DocProject/Help/*.HxT
88 | DocProject/Help/*.HxC
89 | DocProject/Help/*.hhc
90 | DocProject/Help/*.hhk
91 | DocProject/Help/*.hhp
92 | DocProject/Help/Html2
93 | DocProject/Help/html
94 |
95 | # Publish Web Output
96 | *.Publish.xml
97 |
98 | # NuGet Packages Directory
99 | packages/*
100 |
101 | # Windows Azure Build Output
102 | csx
103 | *.build.csdef
104 |
105 | # Windows Store app package directory
106 | AppPackages/
107 |
108 | # Others
109 | #[Bb]in
110 | [Oo]bj
111 | sql
112 | TestResults
113 | [Tt]est[Rr]esult*
114 | *.Cache
115 | ClientBin
116 | [Ss]tyle[Cc]op.*
117 | ~$*
118 | *.dbmdl
119 | Generated_Code #added for RIA/Silverlight projects
120 |
121 | # Backup & report files from converting an old project file to a newer
122 | # Visual Studio version. Backup files are not needed, because we have git ;-)
123 | _UpgradeReport_Files/
124 | Backup*/
125 | UpgradeLog*.XML
126 |
127 | # GhostDoc
128 | *.GhostDoc*
129 |
130 | # Sitecore
131 | src/**/code/App_Config/Include/**/*.example
132 | src/Feature/Analytics/code/App_Config/Include/**/*.config
133 | src/Feature/Social/code/App_Config/Include/**/*.config
134 | !src/Project/TBF/code/App_Config/Include/zTBF/TBF.Project.TBF.config.example
135 | src/Project/TBF/code/App_Config/Include/**/*.config
136 | src/Project/Migration/code/App_Config/Include/**/*.config
137 | src/Project/Microsites/code/App_Config/Include/**/*.config
138 | src/**/code/App_Config/Include/**/*.disabled
139 | src/**/code/App_Config/Include/**/*.exclude
140 | src/**/code/App_Data/MediaCache/*
141 | src/**/codetemp/*
142 |
143 |
144 | # Frontend
145 | .vs/config/applicationhost.config
146 | UpgradeLog.htm
147 |
148 |
149 | #Web Deploy
150 | *.pubxml
151 | publishsettings.targets
152 |
--------------------------------------------------------------------------------
/SitecoreQL/Repositories/IReadOnlyRepository.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 | using Sitecore.ContentSearch;
6 | using Sitecore.ContentSearch.Linq;
7 | using Sitecore.Data;
8 | using SitecoreQL.Query;
9 |
10 | namespace SitecoreQL.Repositories
11 | {
12 | public interface IReadOnlyRepository
13 | {
14 | T GetById(Guid id);
15 | SearchResults GetAll();
16 | SearchResults GetMany(Expression> predicate, Func, IOrderedQueryable> orderBy = null, IEnumerable>> facetOn = null, int take = 0, int skip = 0);
17 | }
18 |
19 | public class ItemRepository : IReadOnlyRepository, IDisposable
20 | {
21 | private readonly IProviderSearchContext _searchContext;
22 |
23 | public ItemRepository()
24 | {
25 | ISearchIndex index = ContentSearchManager.GetIndex($"sitecore_{Sitecore.Context.Database.Name}_index");
26 | _searchContext = index.CreateSearchContext();
27 | }
28 |
29 | public ItemQuery.GraphQLSearchResultItem GetById(Guid id)
30 | {
31 | var queryable = _searchContext.GetQueryable();
32 |
33 | var queryId = new ID(id);
34 | queryable = queryable.Where(x => x.ItemId == queryId)
35 | .Where(x => x.Language == Sitecore.Context.Language.Name)
36 | .Where(x => x.IsLatestVersion);
37 |
38 | return queryable.GetResults().Select(x => x.Document).FirstOrDefault();
39 | }
40 |
41 | public SearchResults GetAll()
42 | {
43 | return GetMany(null);
44 | }
45 |
46 | public SearchResults GetMany(Expression> predicate, Func, IOrderedQueryable> orderBy = null, IEnumerable>> facetOn = null, int take = 0, int skip = 0)
47 | {
48 | var queryable = _searchContext.GetQueryable();
49 |
50 | if (predicate != null)
51 | {
52 | queryable = queryable.Where(predicate);
53 | }
54 |
55 | var sortedQuery = orderBy?.Invoke(queryable);
56 | if (sortedQuery != null)
57 | {
58 | queryable = sortedQuery;
59 | }
60 |
61 | if (facetOn != null)
62 | {
63 | queryable = facetOn.Aggregate(queryable, (current, facetExp) => current.FacetOn(facetExp, 1));
64 | }
65 |
66 | queryable = queryable.Skip(skip);
67 |
68 | if (take > 0)
69 | {
70 | queryable = queryable.Take(take);
71 | }
72 |
73 | return queryable.GetResults();
74 | }
75 |
76 | public void Dispose()
77 | {
78 | _searchContext?.Dispose();
79 | }
80 | }
81 |
82 |
83 | }
--------------------------------------------------------------------------------
/SitecoreQL/Query/ItemQuery.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using GraphQL.Types;
4 | using Sitecore.ContentSearch;
5 | using Sitecore.ContentSearch.SearchTypes;
6 | using SitecoreQL.Converters;
7 | using SitecoreQL.Repositories;
8 | using SitecoreQL.Types;
9 |
10 | namespace SitecoreQL.Query
11 | {
12 | public class ItemQuery : ObjectGraphType
13 | {
14 | public ItemQuery(IReadOnlyRepository repository, IArgumentToExpressionConverter argumentsConverter)
15 | {
16 | Name = "Query";
17 | Description = "Query for Sitecore items";
18 |
19 | var queryArguments = new QueryArguments
20 | {
21 | new QueryArgument {Name = "filter", DefaultValue = new Dictionary()},
22 | new QueryArgument {Name = "first", DefaultValue = 0},
23 | new QueryArgument {Name = "offset", DefaultValue = 0},
24 | new QueryArgument {Name = "sort", DefaultValue = new Dictionary()},
25 | new QueryArgument> { Name = "facets", DefaultValue = new string[] { } }
26 | };
27 |
28 | Field("search",
29 | "Search against all Sitecore items by providing various filter/sort/faceting options.",
30 | queryArguments,
31 | context =>
32 | {
33 | var filter = context.GetArgument>("filter");
34 | var first = context.GetArgument("first");
35 | var offset = context.GetArgument("offset");
36 | var sort = context.GetArgument>("sort");
37 | var facets = context.GetArgument>("facets");
38 |
39 | var filterExpression = argumentsConverter.ConvertToFilter(filter);
40 | var orderByExpression = argumentsConverter.ConvertToOrderBy(sort);
41 | var facetOnExpression = argumentsConverter.ConvertToFacets(facets);
42 |
43 | return repository.GetMany(filterExpression, orderByExpression, facetOnExpression, first, offset);
44 | });
45 |
46 | Field("item",
47 | "Lookup a single Sitecore item by it's ID.",
48 | new QueryArguments(new QueryArgument(typeof(StringGraphType)) { Name = "id" }),
49 | context => repository.GetById(new Guid(context.GetArgument("id"))));
50 |
51 | Field("xpath",
52 | "Lookup Sitecore items via xpath query",
53 | new QueryArguments(new QueryArgument(typeof(StringGraphType)) { Name = "query" }),
54 | context =>
55 | {
56 | var query = context.GetArgument("query");
57 |
58 | return Sitecore.Context.Database.SelectItems(query);
59 | });
60 | }
61 |
62 | public class GraphQLSearchResultItem : SearchResultItem
63 | {
64 | [IndexField("_latestversion")]
65 | public bool IsLatestVersion { get; set; }
66 |
67 | [IndexField("_group")]
68 | public virtual Guid Id { get; set; }
69 |
70 | [IndexField("_parent")]
71 | public virtual Guid ParentId { get; set; }
72 |
73 | [IndexField("site")]
74 | public virtual IEnumerable Site { get; set; }
75 | }
76 | }
77 | }
--------------------------------------------------------------------------------
/SitecoreQL/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/SitecoreQL/SitecoreQL.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
16 |
23 |
24 |
25 |
26 |
27 |
28 |
33 |
34 |
35 |
36 |
37 |
38 |
Loading...
39 |
132 |
133 |
134 |
--------------------------------------------------------------------------------
/SitecoreQL/Converters/ArgumentToExpressionConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Linq.Expressions;
5 | using System.Reflection;
6 | using GraphQL;
7 | using Sitecore.ContentSearch;
8 | using Sitecore.ContentSearch.Linq.Extensions;
9 | using Sitecore.ContentSearch.Linq.Utilities;
10 | using Sitecore.ContentSearch.SearchTypes;
11 | using Sitecore.Data;
12 | using SitecoreQL.Query;
13 | using SitecoreQL.Types;
14 |
15 | namespace SitecoreQL.Converters
16 | {
17 | public class ArgumentToExpressionConverter : IArgumentToExpressionConverter
18 | {
19 | public Expression> ConvertToFilter(IDictionary arguments)
20 | {
21 | ParameterExpression parameterExpression = Expression.Parameter(typeof(ItemQuery.GraphQLSearchResultItem), "item");
22 |
23 | var predicate = PredicateBuilder.True();
24 | foreach (var argument in arguments.Where(a => a.Value != null))
25 | {
26 | var propertyInfo = GetProperty(argument.Key);
27 |
28 | if(propertyInfo == null) continue;
29 |
30 | var @where = GetWhereClause(parameterExpression, propertyInfo, argument.Value);
31 |
32 | predicate = predicate.And(@where);
33 | }
34 |
35 | return predicate;
36 | }
37 |
38 | public Func, IOrderedQueryable> ConvertToOrderBy(IDictionary arguments)
39 | {
40 | SortOption sortOption = arguments.ToObject();
41 |
42 | return q =>
43 | {
44 | Expression> expression = GenerateMemberExpression(sortOption.Field);
45 |
46 | if (expression != null)
47 | {
48 | return sortOption.Dir == SortDirection.DESC ? q.OrderByDescending(expression) : q.OrderBy(expression);
49 | }
50 |
51 | return null;
52 | };
53 | }
54 |
55 | public IEnumerable>> ConvertToFacets(IEnumerable arguments)
56 | {
57 | var p = Expression.Parameter(typeof(ItemQuery.GraphQLSearchResultItem), "i");
58 |
59 | foreach (string argument in arguments)
60 | {
61 | yield return GenerateMemberExpression