ProfileSitecore APIBlogLists Tools Help

Blog


    December 05

    Pluggable DataEngine?

    Recently, we had a question on plugging a custom DataEngine into Sitecore:
     
     
    While the DataEngine itself is not pluggable, the individual commands making up the engine is. That allows you to override any command in the engine. To illustrate what the engine actually does, here is the code for DataEngine.GetItem:
     
        public Item GetItem(ID itemId, Language language, Version version) {
          GetItemCommand command = Commands.GetItemPrototype.Clone();
     
          command.Initialize(itemId, language, version);
     
          return command.Execute();
        }
     
    All methods look like this (with different command prototypes).
     
    To override the behaviour of the GetItemCommand, all you need to do is to assign your own class to the GetItemPrototype property. In V5.3, you have to do this in code (in a hook, for instance). In V5.3.1 you will be able to do it directly from web.config.
     
    For the hook, you can use something like this:
     
      public class MyHook : IHook {
        #region IHook implementation
     
        public void Initialize() {
          Database database = Factory.GetDatabase("master");
     
          database.Engines.DataEngine.Commands.GetItemPrototype = new MyGetItemCommand();
        }
     
        #endregion
      }
     
    Set up the hook in web.config like this:
     
      <hooks>
        <hook type="MyNamespace.MyHook, MyAssembly"/>
        ...
      </hooks>
     
    The command implementation should look something like this:
     
      public class MyGetItemCommand : GetItemCommand {
     
        protected override Item DoExecute() {
          // Do your stuff here and return an item or null.
          // Optionally, you can call base.DoExecute();
        }
     
        public override GetItemCommand Clone() {
          MyGetItemCommand command = new MyGetItemCommand();
          command.Engine = Engine;
          return command;
        }
      }
     
    There is a number of other methods you can override, but DoExecute is the one that does the actual work.
     
    Note that if you override any of the event generating commands (such as SaveItem), the events will still be fired. If you wish to take over the event handling, you should also override the CanExecute and Executed methods.
     
    Also, note that no security checking is performed at this level. The DataEngine is called from the ItemProvider (via ItemManager) which handles securit. If you wish to alter the way security is applied, this might be a better place to hook in (which can be done by using the ItemManager.Provider property).
     
     

    XSLT security

    In V5.3 it is possible to completely disable security for all descendants of WebControl (including XslFile). Simply set the property 'DisableSecurity' to 'true' on the control.

    For XSLT files, we have created two new XSL controls that can be used to enable and disable security for specific sections in an XSLT file.

    An example is provided below:

    <xsl:template match="*" mode="main">
      <h2>Security enabled</h2>
      <sc:enableSecurity>
        <xsl:for-each select="item">
          Child <xsl:value-of select="position()"/><br/>
          <sc:text field="@name"/><br/>
          <br/>
        </xsl:for-each>
      </sc:enableSecurity>

      <h2>Security disabled</h2>
      <sc:disableSecurity>
        <xsl:for-each select="item">
          Child <xsl:value-of select="position()"/><br/>
          <sc:text field="@name"/><br/>
          <br/>
        </xsl:for-each>
      </sc:disableSecurity>
    </xsl:template>


    The <sc:enableSecurity> surrounds its containing statements with a
    Context.Security.EnterState(SecurityState.Enabled) and a Context.Security.ExitState().

    The <sc:disableSecurity> surrounds its containing statements with a
    Context.Security.EnterState(SecurityState.Disabled) and a Context.Security.ExitState().

    After preprocessing, the code will look like this:

      <xsl:template match="*" mode="main">
        <h2>Security enabled</h2>
        <xsl:if test="true()">
          <xsl:value-of select="sc:EnterSecurityState(true())" />
          <xsl:for-each select="item">
          Child <xsl:value-of select="position()" /><br />
         
    <xsl:value-of select="sc:fld('@name', .)" disable-output-escaping="yes" />=
          <xsl:value-of select="sc:fld('title', .)" disable-output-escaping="yes" /><br /><br /></xsl:for-each>
          <xsl:value-of select="sc:ExitSecurityState()" />
        </xsl:if>
        <h2>Security disabled</h2>
        <xsl:if test="true()">
          <xsl:value-of select="sc:EnterSecurityState(false())" />
          <xsl:for-each select="item">
          Child <xsl:value-of select="position()" /><br />
          <xsl:value-of select="sc:fld(
    '@name', .)" disable-output-escaping="yes" />=
          <xsl:value-of select="sc:fld('title', .)" disable-output-escaping="yes" /><br /><br /></xsl:for-each>
          <xsl:value-of select="sc:ExitSecurityState()" />
        </xsl:if>
      </xsl:template>