Sulu: how to query custom entity type? - entity

I have defined custom entity type "matches" and it is back-end editable, everything works as expected.
Now I need a way to query content in that type. Can smart content field type do that? I expected that xml like this would do the trick:
<property name="matches" type="smart_content">
<!-- #see https://docs.sulu.io/en/2.2/reference/content-types/smart_content.html -->
<meta>
<title lang="en">Matches</title>
<title lang="de">Streichhölzer</title>
</meta>
<params>
<param name="provider" value="lists"/>
<param name="types" value="matchevents"/>
<param name="max_per_page" value="5"/>
<param name="page_parameter" value="m"/>
</params>
</property>
But that didn't help. Can it be done with "smart_content" field type? I yes - how? If no - what would be the best way to achieve that?

you have to create a custom DataProvider for your entity and then use your provider in the xml-definition.
So you have to create a repository which implements the DataProviderRepositoryInterface. This repository is used to query the entity.
Furthermore you also have to create the actual dataprovider service. This class should extend form the BaseDataProvider and finally you have to make the service definition with the tag sulu.smart_content.data_provider and an alias.
The alias is used in the xml-file e.g.
<property name="matches" type="smart_content">
<meta>
<title lang="en">Matches</title>
<title lang="de">Streichhölzer</title>
</meta>
<params>
<param name="provider" value="myCustomDataProviderAlias"/>
</params>
</property>
Check out the documentation for a step by step tutorial on how to create a custom data provider. https://docs.sulu.io/en/2.2/cookbook/smart-content-data-provider.html#how-to-create-a-custom-dataprovider

Related

How to link Sitecore Content Editor to a custom Solr search index configured for a certain Data Template?

I have created a custom Solr search index for a specific Data Template as I expect to maintain tons of items created based on that template. As you would guess I organised my items into Sitecore Item Buckets for better performance and also I could configure my Sitecore front-end to utilise that custom Solr search index. Now I would like to optimise the search across my Item Buckets in Content Editor, but it seems that Sitecore takes the master index over any custom indexes. How can I configure Sitecore to use my custom index?
Once you have created your custom Solr index you should also have created a corresponding config file as per one of the example files provided by Sitecore. For instance, for Master DB you can use Sitecore.ContentSearch.Solr.Index.Master.config.example as a config template and simply add a patch:before="*[1]" attribute to your custom index definition as follows:
<?xml version="1.0" encoding="utf-8" ?>
<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
<sitecore>
<contentSearch>
<configuration type="Sitecore.ContentSearch.ContentSearchConfiguration, Sitecore.ContentSearch">
<indexes hint="list:AddIndex">
<index patch:before="*[1]" id="my_sitecore_custom_master_index" type="Sitecore.ContentSearch.SolrProvider.SolrSearchIndex, Sitecore.ContentSearch.SolrProvider">
<param desc="name">$(id)</param>
<param desc="core">$(id)</param>
<param desc="propertyStore" ref="contentSearch/indexConfigurations/databasePropertyStore" param1="$(id)" />
<configuration ref="contentSearch/indexConfigurations/defaultSolrIndexConfiguration" />
<strategies hint="list:AddStrategy">
<strategy ref="contentSearch/indexConfigurations/indexUpdateStrategies/syncMaster" />
</strategies>
<locations hint="list:AddCrawler">
<crawler type="Sitecore.ContentSearch.SitecoreItemCrawler, Sitecore.ContentSearch">
<Database>master</Database>
<Root>/sitecore</Root>
</crawler>
</locations>
<enableItemLanguageFallback>false</enableItemLanguageFallback>
<enableFieldLanguageFallback>false</enableFieldLanguageFallback>
</index>
</indexes>
</configuration>
</contentSearch>
</sitecore>
</configuration>
Now Sitecore will load my_sitecore_custom_master_index index configuration as first priority and utilise it while processing any search queries for your custom items instead of the default Sitecore one.

Content migration of plone dexterity content types in plone 5

I have a dexterity content type defined as model in Employee.xml.
<model xmlns="http://namespaces.plone.org/supermodel/schema"
xmlns:marshal="http://namespaces.plone.org/supermodel/marshal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
i18n:domain="plone">
<schema>
<field name="fullname" type="zope.schema.TextLine">
<description />
<required>True</required>
<title>Firstname and Surname</title>
</field>
<field name="position" type="zope.schema.TextLine">
<description />
<required>True</required>
<title>Position</title>
</field>
</schema>
</model>
Very easy. The class is defined in content.py.
class Employee(Item):
"""Convenience subclass for ``Employee`` portal type
"""
There are some instances of Employee in my database.
Now I want to add a new feature to my content type.
class Employee(Item):
"""Convenience subclass for ``Employee`` portal type
"""
def Title(self):
return self.fullname
Now I can see the fullname of the employee in the folder_contents view. But it works only for instances added after the modification. The "old" content seems to need a migration.
My question: How?
The docs did not help. (https://docs.plone.org/develop/plone/persistency/migrations.html)
The older instances haven't been re-indexed, so everything based on the catalog (collections, navigation, search, folder content, etc.) cannot be aware of their new Title attribute.
Just reindex your portal_catalog and it will be fine.

Are line item properties exposed in the Shopify Order API?

Is it possible to retrieve the custom properties (see here http://wiki.shopify.com/Line_Item_Properties) for all the order's line items within the Order API?
I need to create a custom report for all orders, but they rely on displaying these properties.
Line item properties are exposed by default through the Order API where they exist. Here's an example line-items XML snippet, notice the 'Monogram' property at the bottom:
<line-items type="array">
<line-item>
<id type="integer">223039148</id>
<requires-shipping type="boolean">true</requires-shipping>
<fulfillment-service>manual</fulfillment-service>
<grams type="integer">0</grams>
<price type="decimal">9.99</price>
<quantity type="integer">1</quantity>
<sku/>
<title>All the Tests</title>
<product-id type="integer">90620559</product-id>
<variant-id type="integer">212221205</variant-id>
<vendor>soundcloud</vendor>
<variant-title nil="true"/>
<fulfillment-status nil="true"/>
<name>All the Tests</name>
<variant-inventory-management/>
<properties type="array">
<property>
<name>Monogram</name>
<value>omg</value>
</property>
</properties>
</line-item>
</line-items>
Note that the properties array will be absent if it's empty, so make sure you cater for that in your code.

Jackrabbit - why does search excerpt contain all node properties concatenated?

When I perform a jackrabbit (version 2.2.9) search and I call get row.getValue("rep:excerpt()") the returned string is just all the properties (excluding jcr: properties) concatenated. How do I control this? eg. If I have a property called "description" containing "bla foo bla" when I search for "foo" I would like to see rep:excerpt() return part of just the description.
I tried creating an index config (and I deleted my repository between tests) in an attempt to control what properties were indexed, to no avail.
Workspace.xml...
<SearchIndex class="org.apache.jackrabbit.core.query.lucene.SearchIndex">
<param name="path" value="${wsp.home}/index"/>
<param name="supportHighlighting" value="true"/>
<param name="excerptProviderClass" value="org.apache.jackrabbit.core.query.lucene.DefaultHTMLExcerpt"/>
<param name="indexingConfiguration" value="${wsp.home}/indexing_configuration.xml"/>
</SearchIndex>
indexing_configuration.xml
<?xml version="1.0"?>
<!DOCTYPE configuration SYSTEM "http://jackrabbit.apache.org/dtd/indexing-configuration-1.0.dtd">
<configuration xmlns:nt="http://www.jcp.org/jcr/nt/1.0">
<index-rule nodeType="nt:teneoNode">
<property>description</property>
<property>input</property>
<property>key</property>
<property>comment</property>
</index-rule>
</configuration>
Thanks.
Ted.
You can configure the ExcerptProvider (Javadoc) implementation which is responsible for the rep:excerpt() functionality in the SearchIndex element of you workspace.xml file:
<param name="excerptProviderClass" value="org.apache.jackrabbit.core.query.lucene.DefaultHTMLExcerpt"/>
You might need to plugin in your own implementation for you specific needs.
There is also some - unfortunately rather old - information on the Jackrabbit Wiki.

How do I use structural annotations to set SQL type to Date in model first approach

Is it possible to set type to just date (NOT datetime) via entity framework designer?
I had a look around and the only answer that I've found is a post from MSDN forum from a year ago...
http://social.msdn.microsoft.com/Forums/en/adodotnetentityframework/thread/28e45675-f64b-41f0-9f36-03b67cdf2e1b
I'm very new here and I don't really understand the instructions where they talk about structural annotations...
I can go through the generated SQL script and change each line but I rather not do that...
Structural annotation - nice. It is the first time I heard about this feature but it works. I just tried it. I will try to explain it little bit.
Structural annotations are just random xml added to EDMX file. EDMX file is in fact just XML wich has 4 parts - CSDL, MSL, SSDL and part related to positioning elements in the designer.
CSDL describes entities and associations among entities (defined in the designer)
SSDL describes tables and relations
MSL describes mapping between CSDL and SSDL
If you start with model first (you want to generate database from your model), you have only CSDL part and both SSDL and MSL will be generated by some automatic process (T4 templates executed in workflow) once SSDL is created another T4 template will generate SQL script for database creation.
Structural annotation described in linked MSDN forum's thread is a hint. You will place structural annotation into CSDL part of the EDMX (you must open EDMX as XML - click on the file in solution explorer and choose Open with). My test CSDL describes single User entity with three properties (entity is visible on screenshot later in the answer):
<!-- CSDL content -->
<edmx:ConceptualModels>
<Schema xmlns="http://schemas.microsoft.com/ado/2008/09/edm"
xmlns:cg="http://schemas.microsoft.com/ado/2006/04/codegeneration"
xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator"
xmlns:annotation="http://schemas.microsoft.com/ado/2009/02/edm/annotation"
xmlns:custom="http://tempuri.org/custom"
Namespace="Model" Alias="Self" >
<EntityContainer Name="ModelContainer" annotation:LazyLoadingEnabled="true">
<EntitySet Name="UsersSet" EntityType="Model.User" />
</EntityContainer>
<EntityType Name="User">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Type="Int32" Name="Id" Nullable="false" annotation:StoreGeneratedPattern="Identity" />
<Property Type="String" Name="Login" Nullable="false" />
<Property Type="DateTime" Name="CreatedAt" Nullable="false">
<custom:SqlType edmx:CopyToSSDL="true">Date</custom:SqlType>
</Property>
</EntityType>
</Schema>
</edmx:ConceptualModels>
I have added custom namespace definition in Schema element: xmlns:custom="http://tempuri.org/custom" and defined custom structural annotation for CreatedAt property:
<Property Type="DateTime" Name="CreatedAt" Nullable="false">
<custom:SqlType edmx:CopyToSSDL="true">Date</custom:SqlType>
</Property>
The name of the namespace or element used for structural annotation are not important - it is absolutely up to you what names do you use. The only important thing is edmx:CopyToSSDL="true" attribute. This attribute is recognized by T4 template used for SSDL creation and it just takes this element and places it to SSDL. Generated SSDL looks like:
<Schema Namespace="Model.Store" Alias="Self"
Provider="System.Data.SqlClient" ProviderManifestToken="2008"
xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator"
xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
<EntityContainer Name="ModelStoreContainer">
<EntitySet Name="UsersSet" EntityType="Model.Store.UsersSet" store:Type="Tables" Schema="dbo" />
</EntityContainer>
<EntityType Name="UsersSet">
<Key>
<PropertyRef Name="Id" />
</Key>
<Property Name="Id" Type="int" StoreGeneratedPattern="Identity" Nullable="false" />
<Property Name="Login" Type="nvarchar(max)" Nullable="false" />
<Property Name="CreatedAt" Type="datetime" Nullable="false">
<custom:SqlType xmlns:custom="http://tempuri.org/custom">Date</custom:SqlType>
</Property>
</EntityType>
</Schema>
The only point was moving the structural annotation to SSDL. All annotations are accessible in metadata through some name value collection. Now you need to modify T4 template responsible for SQL script generation to recognize this annotation and use the value defined in the annotation instead of type defined in the property. You can find the template in:
C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Microsoft\Entity Framework Tools\DBGen\SSDLToSQL10.tt
Copy template file to new location (so that you don't modify the original one) and replace default table creation with this:
-- Creating table '<#=tableName#>'
CREATE TABLE <# if (!IsSQLCE) {#>[<#=schemaName#>].<#}#>[<#=tableName#>] (
<#
for (int p = 0; p < entitySet.ElementType.Properties.Count; p++)
{
EdmProperty prop = entitySet.ElementType.Properties[p];
#>
[<#=Id(prop.Name)#>] <#
if (prop.MetadataProperties.Contains("http://tempuri.org/custom:SqlType"))
{
MetadataProperty annotationProperty = prop.MetadataProperties["http://tempuri.org/custom:SqlType"];
XElement e = XElement.Parse(annotationProperty.Value.ToString());
string value = e.Value.Trim();
#>
<#=value#> <# } else { #> <#=prop.ToStoreType()#> <# } #> <#=WriteIdentity(prop, targetVersion)#> <#=WriteNullable(prop.Nullable)#><#=(p < entitySet.ElementType.Properties.Count - 1) ? "," : ""#>
<#
}
#>
);
GO
Now the last point is changing the template used for SQL script generation. Open EDMX file in the designer and go to model's properties (just click somewhere in the designer while you have properties window opened). Change DDL Generation Template to the template you modified.
Run Generate Database from Model and it will create SQL script containing:
-- Creating table 'UsersSet'
CREATE TABLE [dbo].[UsersSet] (
[Id] int IDENTITY(1,1) NOT NULL,
[Login] nvarchar(max) NOT NULL,
[CreatedAt] Date NOT NULL
);
GO
This is probably the most advanced and hidden feature of EDMX I have seen yet. Annotations together with custom T4 templates can get you a lot of control over both class and SQL generation. I can imagine using this to define for example database indexes or unique keys when using model first or add selectively some custom attributes to generated POCO classes.
The reason why this is so hidden is that there is no tooling support in VS out-of-the box to use this.
From NuGet look for TiraggoEdmx, it serves up all the low level information from your EDMX files in a very nice way. See http://brewdawg.github.io/Tiraggo.Edmx/