Perform logic when specific template is published - sitecore

I have a template set up that I need to perform some logic on when it's published. When an item based on this template is published they want me to perform some basic CRUD operations on a table in an external database so everything is in sync. But that's kind of beside the point.
What I have set up right now is a new processor in the publishItem pipeline. I've found I can access the PublishItemContext.PublishOptions.RootItem to access the template, which I can compare on and perform logic as necessary. The problem is with so called deep publishes. I'm only seeing my processor firing for the root item, not for any of the sub items.
So, my questions is if there is a way to access every item that's being published, not just the root item?
A co-worker suggested I grab timestamps at the beginning of the pipeline and the end, and use the HistoryManager to check on what all has changed... but that seems pretty heavy-handed to me. I can't help but feel like there ought to be a property or setting nested in here somewhere where I can access everything that's being published.
I'd appreciate any assistance you folks can offer.
Oh, we're on version 6.5 for this project, I'm sure that'll be relevant.

Looks like you'll want to add a handler node to
<event name="publish:end">
event in the web.config. Documentation can be found here: http://sdn.sitecore.net/articles/api/using%20events.aspx

You can use `publish:itemProcessed' event:
<event name="publish:itemProcessed">
<handler
type="My.Assembly.Namespace.ItemProcessedProcessor, My.Assembly"
method="ItemProcessed">
</handler>
</event>
And then use args.Context.VersionToPublish:
using System;
using Sitecore.Data;
using Sitecore.Publishing.Pipelines.PublishItem;
namespace My.Assembly.Namespace
{
public class ItemProcessedProcessor
{
private static readonly ID ChosenTemplateID = ID.Parse("{ID-SHOULD-BE-HERE}");
public void ItemProcessed(object sender, EventArgs args)
{
ItemProcessedEventArgs itemProcessedEventArgs = args as ItemProcessedEventArgs;
PublishItemContext context = itemProcessedEventArgs != null ? itemProcessedEventArgs.Context : null;
if (context != null && context.VersionToPublish != null)
{
if (context.VersionToPublish.Template.ID == ChosenTemplateID)
{
// do the logic here
}
}
}
}
}

Well, as it turns out, my problem was not nearly as complicated as I expected. As was pointed out to me, of course looking at PublishItemContext.PublishOptions.RootItem will only return the root item. The processor actually is being hit by each item being published, I'm just looking at the wrong field.
var item = PublishItemContext.PublishHelper.GetSourceItem(context.ItemId);
This gets me what I need.
PEBKAC

Related

How do I opt-out of privacy sensitive redaction for locked device?

I can't seem to make my watch WidgetKit complication to show while the device is locked. This is done in the weather complication and can be seen if you take off your watch and set it down, but my widget is redacted until unlocked.
I tried adding .unredacted to my root widget view but same behaviour. Is this something I can do from the app code or is this only controlled by the user? I don't remember setting this on the weather complication so I thought it set itself as public which is what I would like to do. It is not clear how to achieve this in the docs.
I found a hint to the solution in this post. Since I did not completely understand it, I tried some ideas and found a working solution for a single widget. An extension to multiple widgets in a widget family should work accordingly.
#main
struct ShopEasy_Widgets: Widget {
let kind: String = "ShopEasy__WidgetKit_Extension"
var body: some WidgetConfiguration {
StaticConfiguration(kind: kind, provider: Provider()) { entry in
ShopEasy_WidgetKitsEntryView(entry: entry)
.unredacted()
}
.supportedFamilies([.accessoryCircular, .accessoryInline, .accessoryRectangular, .accessoryCorner])
}
}
Did you already implement WKSupportsAlwaysOnDisplay? If not, ensure that you have done so. I believe it takes a boolean value. If you have already done so, I have seen that specifying whether or not each section of your complication as either .unreadacted or .redacted can help to solve this issue.

Can I guarantee publishing of an item I've just created?

I've got a situation where I want end-users to be able to create new Sitecore items... and then immediately be able to navigate to the Item's URL. Obviously the item will have to be published... but this happens in something of a black box. Is there a way to guarantee an item has been published from Master to Web?
Alternately, I could create the Item in the Web DB... then re-create/copy a Master version at some point. But this strategy seems fraught with peril. And maybe just a bad idea in general.
Suggestions? Am I being needlessly paranoid about creating items directly in Web?
I'll start by saying my answer is not necessarily advisable. However, depending on your situation it should work.
If the items that users are creating always have the same template you could try creating a custom item resolver that falls back to using the Master database.
Allow Sitecore to attempt to resolve the item normally.
When it fails, look in the Master database.
If the item is in there, make sure it has the correct template
Set the found item as the context item.
Using this method, you can publish the items from Master->Web s normal, but you don't have to wait until publishing is completed to see it.
Once again, this should solve the problem, but it's up to you to weigh the risks of serving up Master DB content.
You can't "guarantee" because publishing may be queued and won't go live instantly. Instead if you need instant access, I recommend a preview site that points to the master database:
How to Setup a Sitecore Preview Site to Review Content Before Publishing
You could create a event mapping to a class with the code to publish the item. In the code you can define any rule you want regarnding whether to publish or not.
<event name="item:saved">
<handler type="YourType.ItemEventHandler, YourType" method="OnItemSaved" />
</event>
And the OnItemSaved would look like this: (not tested)
protected void OnItemSaved(object sender, EventArgs args)
{
if (args == null)
{
return;
}
Item item = Event.ExtractParameter(args, 0) as Item;
var webDb = Sitecore.Configuration.Factory.GetDatabase("web");
var masterDb = Sitecore.Configuration.Factory.GetDatabase("master");
foreach (Language language in masterDb.Languages)
{
var options = new PublishOptions(masterDb, webDb, PublishMode.SingleItem, language, DateTime.Now)
{ RootItem = item, Deep = true };
var myPublisher = new Publisher(options);
myPublisher.Publish();
}
}
And about creating the item in the web db, I also wouldn`t go that way. It would be replaced by the default publishing process unexpectedly.
Personally i don't like front-end user creating items in master database, i feel only content authors/editors should be the ones who create items from either content editor or page editor.
There is no guarantee the item gets published instantly, I would recommend you to store any user-created data in a separate database and on the redirect URL just read the data from this database.

Sitecore - Publish subitems checkbox dynamically populating

I have seen a post in Stackoverflow regarding how to hide the "Publish sub items" from Sitecore publish pop up by overriding the visibility of the checkbox. This is really good which can avoid so many performance issues when there is large amount of content in the content tree.
Is it possible to dynamically hide this checkbox? Coz, as a developer I need to publish other Sitecore items (Templates, Settings etc.) when it comes to deployments. Therefore "Publish sub items" is a essential feature for me. Still I need it to be hidden from content editors.
How can I achieve this task?
(If there was a security configuration to control access to this feature it would have been ideal)
First of all you need to change Publish.xml file from Folder:
\web\sitecore\shell\Applications\Dialogs\Publish\
You need to change CodeBeside it will look like this :
<WizardForm CodeBeside="YourNameSpace.CustomPublishForm,YourAssembly">
Your class will be :
class CustomPublishForm:PublishForm
{
public CustomPublishForm()
: base()
{
}
protected override void OnLoad(System.EventArgs e)
{
base.OnLoad(e);
//you need to change here with users that you want to see CheckBox
if (Sitecore.Context.User.Name.Equals("lorenipsum"))
{
base.PublishChildren.Visible = true;
}else
{
base.PublishChildren.Visible = false;
}
}
}
I tested and it's working fine this solution you have just to do minor changes to your requirements.
Here is the post: Sitecore - Hide "Publish Subitems" from publish pop up
You'll want to alter the CodeBeside attribute from Sitecore.Shell.Applications.Dialogs.Publish.PublishForm,Sitecore.Client to your own class that wraps that one. In your own class override any methods you need to in order for the logic to show or hide the box per your needs, e.g. user is in a certain role.
Be aware that such modifications make upgrades a bit harder.
Copying the Publish.xml and triggering this from a new button makes it clear for everyone, that this is not Sitecore but your own logic.

Sitecore context in HttpHandler

I have HttpTaskAsyncHandler in my sitecore solution and i call it I have sutup IngnoreUrlPrefix and etc.
By some reason i can't get access to SC.Context.Database Database is null in ProcessRequestAsync(HttpContext context) method,
it looks like I don't access to Sitecore context in HttpHandler.
How to resolve it ?
Thanks.
You wont be able to access Sitecore Context (Database or Item) in the Handler. We have confirmed this with Sitecore Support for our task.
The best way is Implement a Processor in the Request pipeline begin.
How to Implement
Inherit HttpRequestProcessor in your class found in (using Sitecore.Pipelines.HttpRequest;)
and add that Processor after SiteResolver in < httpRequestBegin >
<processor type="Sitecore.Pipelines.HttpRequest.SiteResolver, Sitecore.Kernel" />
<!-- Custom Module -->
<processor type="SND641.Customization.RobotsModule, SND641" />
If you choose to ignore your script file (by using IgnoreUrlPrefix), then you it will not be processed by Sitecore's request pipeline and thus will not have a Sitecore context.
I think you can solve it by removing your url prefix from IgnoreUrlPrefix and make sure the file extension of your handler is added to the allowed extensions parameter of the FilterUrlExtensions pipeline processor:
<processor type="Sitecore.Pipelines.HttpRequest.FilterUrlExtensions, Sitecore.Kernel">
<param desc="Allowed extensions (comma separated)">aspx</param>
</processor>
This way you can call your script and still have Sitecore process all the pipelines.
You can get context without pipeline. Along with web.config handler definition, you will need to add under customHandler. It helps in getting sitecore context. E.g
<customHandlers>
<handler trigger="blogfeed.xml" handler="blogfeed.xml" />
</customHandlers>
I'm sorry if I'm not getting exactly what you are trying to do. But by working with handlers I did have issues that my code was not able to access the sitecore object even when I updated the web.config and
I noticed that my handler was like this:
public class GetHandler: IHttpHandler
{
...
}
by adding the System.web.SessionState.IrequiresSessionStatem, like this:
public class GetHandler : IHttpHandler, System.Web.SessionState.IRequiresSessionState
{....}
then everything started to work and I was able to get items from sitecore without issues:
Public void ProcessRequest(HttpContext context)
{
Database webdb = Factory.GetDatabase("web");
}
previous my change the webdb was coming with nothing and the code was coming back with "Command "Sitecore.Database" is not valid"
after that changes, as I said, everything worked for me.
I hope this helps and adds some value to the existing answers.
regards,

Sitecore 6.5 DMS - Registering a goal completion via the API

I want to register a goal/conversion on my Sitecore 6.5 site using the API rather than a 'thank-you' page.
I've seen this question about how to do it Sitecore OMS - achieving a goal on a form submission but the answer relates to the API prior to Sitecore 6.5 where it was overhauled quite significantly.
Has anyone done this? Or has this functionality been intentionally removed?
Have you tried something like
protected void btnSubmit_Click(object sender, EventArgs e)
{
if (Sitecore.Analytics.Tracker.IsActive && Sitecore.Analytics.Tracker.CurrentPage != null)
{
PageEventData eventData = new PageEventData("My Goal Name");
eventData.Data = "this is some event data.";
VisitorDataSet.PageEventsRow pageEventsRow = Sitecore.Analytics.Tracker.CurrentPage.Register(eventData);
Sitecore.Analytics.Tracker.Submit();
}
}
That should register the goal on the currentpage, but not before you decide to in your code
You can also use a modified version of the code which references the Goal Item by its GUID:
if (Sitecore.Analytics.Tracker.IsActive && Sitecore.Analytics.Tracker.CurrentPage != null)
{
PageEventItem goal = new PageEventItem(Sitecore.Context.Database.GetItem("GOALGUID"));
VisitorDataSet.PageEventsRow pageEventsRow = Sitecore.Analytics.Tracker.CurrentPage.Register(goal);
Sitecore.Analytics.Tracker.Submit();
}
Make sure you have deployed and published your goal and or goal category too as the code will fail otherwise.