What's a Non-Delivery Custom Renderer? - tridion

SDL Live Content describes the use case for Renderers as "manipulating the output produced by the rendering process" for Component Presentations. This falls between Content Manager and Content Delivery, specifically under Content Distribution / Publishing.
Rather than adding a Template Building Block (TBB) to all templates, we can use a custom renderer to "globally" change all CP's output. We can also use a renderer to publish item types not currently rendered. We can add a custom resolver for this item type along with a custom renderer and CD-side code.
We would implement IRenderer under Tridion.ContentManager.Publishing.Rendering in a .NET project and add the resulting dll to the CMS's GAC.
Questions
I can see how we would use a renderer to maybe manipulate or even wrap all outputted markup or maybe wrap all CPs.
Is this for "raw" manipulation of whatever our templates output? In other words, do we get access to any of the CM or CD APIs?
Does this renderer logic apply to all publications and templates in a given CMS instance?
The documentation refers to item types, are those Tridion item types such as TBBs?
Bart Koopman also describes how Custom Renderers work in the context of the other extension points in How To Tackle Integrations article on SDLTridionWorld.
I understand is distinct from Delivery-Side Renderers described by Jaime Santos Alcón?

This is indeed something that would be executed every time the standard renderer is invoked. While the use case for Custom Resolvers is easier to understand, the principles are the same and they're both part of the Publishing Pipeline.
I will always advise that instead of creating a custom renderer that will execute every time you render a template, you should use a Template Building Block that is added to all of your templates with that same functionality. Creating a custom renderer will likely be forgotten at some point in time and then you'll wonder why the output is different all of a sudden when nothing changed.

Related

Modular architecture to encapsulate functions in Symfony2

What I want to develop....
I am currently developing a SaaS-solution (Symfony2) to build HTML-presentations or better slide shows. Users can log into an administration UI and create presentations. This presentations can be played later. A presentation consists of elements. The elements can be images, texts, videos, pdf and more.
This element types should be encapsulated from the user interface. So extern developers can develop such new modules (element types) with defined interfaces and inject it into the system.
If a new module is finished, we move it to a specific directory in the symfony2 directory and the system detect the new module. No hardcoded-changes in the administration ui system should be neccessary.
Each module has a own "product-number". So we can use a database to enable or disable modules for different users.
What functions must be implemented by a module?
In the administration ui the user has the possibility to create a presentation and add elements of different types (the modules). User sees a timeline with the elements. When he clicks on an element, the editor for this element will be shown under the timeline (Parent-Child-View). Each module has different editors. A text-module needs other configuration-possbilities than an image-module.
So, in admin UI we need functions to edit elements:
createNewElement() creates new entry in the database (module has own tables, e.g. mod_text_elements)
renderEditorView() generates HTML which will be shown in the administration ui with module-specific inputs. E.g. image-upload/crop, WYSIWYG-editor, ...
saveEditorInputs() the module needs to handle the data entered in the editor and save it to the elements entry in the database
deleteElement() to delete an element
The output for the presentation:
Later we want to play this presentation. So a loop goes through the presentation elements and asks the modules of the element what and how to show it.
renderPresentation() to render (HTML) an element for the presentation
Database
I've made a little er-diagram of a possible solution to save the information about modules and elements in a database. The yellow entities are module-specific tables.
How to realize this in Symfony2?
My frist idea is to define an interface which have to be implemented by the modules. But which class has to implement this? Controllers?
Are modules = bundles?
How to realize the View-in-View of the editor? The editor of the module (e.g. renderEditorView()) should be viewed in the user interface of the administration ui.
I'd do it by hooking in to the EventDispatcher Component.
Your 'Master' Controller would define a set of events which correspond to the standard CRUD actions you've defined above ... onCreateNewElement(), onRenderEditorView(), etc. You'll probably find a dozen more to provide hooks for as you build your application (allowing plugins to add tools to a toolbar for example).
You'd define a Service (this doesn't HAVE to be a Controller Class), which looks for new 'modules' and adds their correctly-named methods as listeners for your custom application events.
Are modules = bundles? Well, that's entirely up to you. Are you going to provide a method for users to 'install' new modules specifically for your application? Then what a module needs to look like is entirely up to you. Are you going to slip Composer into the mix and allow modules to be installed that way? Places a couple of constraints on the structure, but still pretty much up to you.
How to realise the View-in-View? Again, that comes down to exactly how you define the interface for your 'Event Plugins' and what kind of access they have to resources like TWIG and YAML config.
The question you're REALLY asking is How do I add functionality to an application without hacking existing code ... and the answer is EventDispatcher. The rest is up to you.
There is another way to expand codebase with custom "modules": Dependency Injection Tags.
It works like this:
You create core of the app, which implements basic functionality and registers compiler pass which handles code extension
Modules can be part of the core app OR moved to external bundles
Each module must be registered in DI container with tag supported by your core app, so can be handled properly (adding menu positions, new element types as in your example)
Symfony DI compiles all services and stuff so all modules are available within app instantly (so you can for example iterate over collection of prepared items without need to dynamically building it)
In my opinion EventDispatcher is better for handling real-time actions, like sending notifications when new entity is created (e.g. controller/service dispatches event, some bundle subscribes it and send notification).
When you want to extend core I would recommend DI tags. Of course you have to build all the core (interfaces and whole architecture) so modules can extend existing services' data, then you only use your services.
Whole Symfony full-stack framework is based od this tags, so there is a lot of existing code to investigate for getting the concept.
Please let me know if it's clear enough what I wrote and what's in Symfony docs. If you need some additional info, I'll try to help.

Can Sitecore templates be used to store SQL Queries or JavaScript

We are building a Page with dynamic functionality using ASP.NET + Sitecore 7.0.
Is it practical and appropriate use Sitecore templates for:
SQL Stored Procedure Name to be invoked
JavaScript to be invoked
ColumnNames to be used etc (related to coding customization)
Or should these configuration properties remain inside the ASP.NET Project itself?
What is the primary purpose of Data Templates in Sitecore?
Are they for developer customization or customer-level customization?
The purpose of a data template in Sitecore is to define the set of fields for content items which inherit from that template. - Think of a data template as a class and the content items (pages) as instances of that class.
Templates are usually used to define the user-editable content of pages within a site, that being said you can have items to store information which is not managed by regular content editors. The question is where do you draw the line between things which should be put into Sitecore and things which should be a part of the solution. My advice is only put things in Sitecore if they need to be there. If you have to have the ability for editors or admins to configure those settings/properties.
I would say that putting SQL/ColumnNames is probably a bad idea unless you are building some sort of report builder interface in which case it may be essential?
Likewise with placing JavaScript into Sitecore; this can be OK in moderation (e.g. snippets of analytics code which content editors may want control over?). If you're placing whole libraries of JavaScript into Sitecore, you're probably doing it wrong.
One final point to note is findability/re-factorability of code: if you have code spread between Sitecore and your solution, it can make it very difficult to maintain as it is difficult to get a complete overview of code involved.

Plone schema extender and custom content types

Is it possible to create an extender of a content type (just adding a couple new fields) that is also accepted by any custom content types using the original type's schema?
I am working on an idea I had for a new feature on PloneFormGen. I originally was going to fork and modify the core product, but figured it would be more acceptable to create a separate add-on that extends PFG. So, I started creating my extender.py and all the necessary bits with it to extend PloneFormGen Form Folder.
However, our company has a custom content type that is an extension of the form folder. That got me thinking instead of just accounting for the standard Form Folder, could I either account for all types using form folder as a base, or provide a control panel where the site admins can specify the types for the extender to apply to?
Or, is there a better way to create our custom types so it not only grabs the core schema, but any extenders for it as well?
To explain in more detail what I am adding, it is not a field, or an action adapter. Basically, it is a new feature called Skip Logic. It provides the ability to hide/display fields based on values of other fields live using jQuery. As opposed to creating custom JS overrides for each form, this allows a content editor, or whoever builds the forms, to control this functionality with no code. There is a JS file that is loaded, and it uses a JSON string to determine the hide/show functionality. I created a form template that can be used to manage this which pulls in all available form fields to choose from.
My idea for implementation was to add two new catalog indexes to the PFG form. One is a boolean which toggles skip logic enabled/disabled. The other is a string which holds the JSON string, which is created by using the form UI (think like a new tab similar to QuickEdit).
If anyone has a better solution for how to implement, I am all ears. Either modifying the core product, or extending it were the only two I could think of.
SchemaExtenders adapt an interface and not the class itself, so for your simple "extending FormFolder" example, you shouldn't need to do anything special. You can even adapt to a marker interface that doesn't do anything useful by itself and make classes implement that interface "externally" (just excerpts from local code here):
class IIllustratableContent(Interface):
"""This content has an image reference it sometimes might use"""
class IllustratableExtender(object):
adapts(IIllustratableContent)
implements(
ISchemaExtender,
IBrowserLayerAwareExtender,
)
# do stuff
and configure.zcml:
<adapter
name="illustratedContent"
factory=".illustratedContent.IllustratableExtender"
provides="archetypes.schemaextender.interfaces.ISchemaExtender"
/>
<five:implements
class="Products.ATContentTypes.content.document.ATDocument"
interface=".illustratedContent.IIllustratableContent"
/> <!-- and for some other classes, too -->

How edit and save the tridion default templates (TBB's)?

How to edit and save back the default tridion template building blocks say for Ex(Default Finish Actions) provided by SDL?
Where can i found the soucre of default TBB's? After locating and editing the TBB's, how to save back in TCM?
Editing default templates provided by SDL is not supported. They are stored in DLL and there's no way you can customize it. Maximum you can do is to disable some of the templates from being created. Alternatively you can can create your own set of default templates.
You can use the Template Builder to assemble and (test) run Compound Templates (Page and Component Templates). You can access the Template Builder from the Tools tab in the Ribbon.
The default TBBs should not be changed.
.NET TBBs are either C# fragments with the code directly accessible, or classes that implement the ITemplate interface.
Please see the following blog post to get you started:
http://www.createandbreak.net/2011/11/template-building-blocks-via-net.html
The code for (an older version of) most of the Default Template Building Blocks can be found on the Tridion forum (http://forum.sdltridion.com).
(I don't have access anymore, but maybe somebody can edit my answer and provide the link)
As others have said though, you risk getting into support trouble if you simply modify and replace them. It might be better to:
take the code from the forum as a starting point
create your own variant, making the modifications you need
compile this into a new TBB
replace the standard TBB in the Default Finish Actions with your own variant
That way you can accomplish most things, without risking support problems. When they doubt whether you broke is, you can just swap out your own variant for the original and prove them wrong.

Best way to render arbitrary number of heterogenous Items?

I have a checkout page on my site which lists items that customer is purchasing... and below the basic list is a "Detailed Invoice" section where they can see specific info on each. Up 'til now I only had two different types of items that could be purchased, so the detailed listing was fairly easy to handle. Now I'm adding four additional and completely different things that are purchasable... so the question: What is a good way of handling this sort of rendering using Sitecore sublayouts? (Currently, I just use a Repeater and hide/show appropriate fields)
The good news is, for each line item in an order there is an associated Sitecore Item instance. If the Sitecore API was better suited to object-oriented methodology, I might create a Render() method on each of my object types in question. But of course they are each Sitecore.Data.Items.Item objects. Subclass Item? This seems like overkill for just this task...
Something I've considered is a Sublayout/user control for each different item type... and then dynamically add them to a Placeholder on the invoice page. This seems reasonable... Thoughts? The downside is then the ugly code that has to match up the user control with the item... based on TemplateID maybe?
Anyway, just looking for some suggestions here.
Building classes to represent Sitecore data is not an unreasonable idea. This is a perfect scenario to to do it. Whenever I build project I always have classes generated using the Custom Item Generator in case I need template-specific field access. I also do everything as sublayouts so I can see your dilemma.
Are all/most of the fields unique to each product? You don't have a generic product template that each product instance uses?
These are the options I can think of myself (worst to best IMO):
Create a class to represent each unique template. The Custom Item Generator may work, but it may confuse you the first time. You can always make your own classes where you pass the Sitecore item into the constructor and create properties to access fields. Then use regular .NET controls and bind data to the front-end based on which template your item uses and using the strongly-type class for the template. This will likely be messy code of many if-else's.
Create a unique sublayout for each unique template in Sitecore. In your repeater that loops over the items, based on which template the item is, add the right sublayout to the placeholder using new Sublayout() and set the DataSource as the Sitecore item (here's code to access the DataSource). That way you abstract the implementation to each unique template.
Create classes for each template as mentioned in #1, but abstract across them all with an interface. In your repeater's ItemDataBound, implement data via the interface. This highly depends on how the fields compare and contrast from template to template. If you can force yourself to reduce the unique fields into the interface's members then each class that represents a template can just implement your interface. This allows for the future addition of more unique templates, as long as you continue to implement the interface.
This to me seems like a good place to use the "Presentation Inversion of Control" Sitecore pattern (as named by Aware Web).
http://www.awareweb.com/AwareBlog/Presentation%20Inversion%20of%20Control%20part%202.aspx
Though the blog post discusses this more in a context of user-placed items, it works here too. If you have a template for each product type, you could define presentation details on each (perhaps in a separate Device) that define the control which can render that item in the cart. Then you can read the RenderingReference's off the item, and place them into the page. This makes for a flexible, extensible system that allows you to handle different output for different types of products.
This is close to the solution you describe (Sublayout for each product type), but allows the sublayout to be data driven instead of conditional logic for each TemplateID. (Note you will need to assign a dummy "main layout" in the presentation details as well.)

Resources