Getting Orchard fields from different parts - orchardcms

In an Orchard summary view I'm displaying a content item that could be a Page, a Blog Post or a Projection.
I've attached a Media Picker field to all these types and called it Picture.
I'm currently using this horrible bit of code to access the media picker from the content item:
if (contentItem != null)
{
try
{
mediaPicker = (MediaLibraryPickerField) contentItem.Blog.Picture;
}
catch (Exception e) {}
if (mediaPicker == null)
{
try
{
mediaPicker = (MediaLibraryPickerField)
contentItem.Page.Picture;
}
catch (Exception e) {}
}
if(mediaPicker == null)
{
try
{
mediaPicker = (MediaLibraryPickerField) contentItem.ProjectionPage.Picture;
}
catch (Exception e) {}
}
}
There must be a better way?

Another way is using Linq:
var mediaPicker = (MediaLibraryPickerField)
(from part in ((ContentItem)contentItem).Parts
from field in part.Fields
where field.Name == "Picture"
select field).FirstOrDefault();
It's clean, and works for future new types that have a Picture field.
Here's the fluent eqivalent:
var mediaPicker = (MediaLibraryPickerField)
((IEnumerable<ContentPart>)contentItem.Parts)
.SelectMany(p => p.Fields)
.FirstOrDefault(f => f.Name == "Picture");

You can cast the item to dynamic and access the fields as you do on templates
dynamic content = (dynamic)contentItem;
var mediaPicker = content.BlogPart.Picture;
Now you have the field on mediaPicker. One disadvantage is that you lose IntelliSense. If the field does not exists I think that mediaPicker is null.

Related

Acumatica - FieldDefaulting update ImageUrl from DAC extension

I am trying to update the Inventory Item ImageUrl if it is found to be null with some conditions. I have added a Usr field called UsrStyleImg to the Item Class screen. This field is for a basic image of an item and it is stored in the database. The functionality I want is if the Inventory Item does not have an image in the ImageUrl then it will default to the UsrStyleImg that is connected with the ItemClassID. ItemClassID is also found on the Stock Item Screen. Here is the code I have in the InventoryItemMaint graph:
protected void InventoryItem_ImageUrl_FieldDefaulting(PXCache cache, PXFieldDefaultingEventArgs e)
{
var row = (InventoryItem)e.Row;
if (row == null) return;
var item = (INItemClass)PXSelect<INItemClass, Where<INItemClass.itemClassID, Equal<Current<InventoryItem.itemClassID>>>>.Select(Base, row.ItemClassID);
var image = PXSelect<InventoryItem, Where<InventoryItem.imageUrl, Equal<Current<InventoryItem.imageUrl>>>>.Select(Base, row.ImageUrl);
if (image != null)
return;
else {
e.NewValue = item.GetExtension<INItemClassExt>().UsrStyleImg;
}
}
The code compiles fine but when I test with an Item that has an Item Class attached to it with an image in the INItemClass table called UsrStyleImg it does not populate to the imageUrl found in the Inventory Item table or the Stock Item screen. I have also tried this with FieldSelecting and using the e.ReturnValue with still the same results.
If I need more clarification please let me know.
Try using a RowSelecting Event
protected virtual void InventoryItem_RowSelecting(PXCache sender, PXRowSelectingEventArgs e)
{
InventoryItem row = e.Row as InventoryItem;
//Extra checks to prevent infinite loops
if (row != null && !string.IsNullOrWhiteSpace(row.InventoryCD) && Base.Item.Cache.GetStatus(row) == PXEntryStatus.Notchanged)
{
if (!string.IsNullOrWhiteSpace(row.ItemClassID))
{
//You must always use a PXConnectionScope if Selecting during RowSelecting
using (new PXConnectionScope())
{
//If you're going to pass in a value in .Select, use Required instead of Current.
INItemClass itemClass = PXSelectReadonly<INItemClass, Where<INItemClass.itemClassID, Equal<Required<INItemClass.itemClassID>>>>.Select(Base, row.ItemClassID);
if (itemClass != null && string.IsNullOrWhiteSpace(row.ImageUrl))
{
INItemClassExt itemClassExt = itemClass.GetExtension<INItemClassExt>();
//To prevent unneeded update if it's blank
if (!string.IsNullOrWhiteSpace(itemClassExt.UsrStyleImg))
{
row.ImageUrl = itemClassExt .UsrStyleImg;
//Force set the status in the Cache, otherwise it infinite loops
Base.Item.Cache.SetStatus(row, PXEntryStatus.Updated);
Base.Item.Update(row);
}
}
}
}
}
}

SharePoint online (O365):How to get a parent item URL?

Having the following URL
https://test.sharepoint.com/shared%20documents/MyFolder1/myImg1.jpeg
I need to send a request for parent URL of this item (in this specific case image) and to get a response:
https://test.sharepoint.com/shared%20documents/MyFolder1/
Does such a request exists if using a CSOM or Office 365 Activity API?
Where in documentation can i find such examples?
static public string ReturnFileParentUrl(string url)
{
try
{
Uri uri = new Uri("https://XXX.sharepoint.com/");
using (var ctx = GetContext(uri, "YYY#DOMAIN.com", "password"))
{
Microsoft.SharePoint.Client.File item = ctx.Web.GetFileByServerRelativeUrl(url);
ctx.Load(item);
ctx.ExecuteQuery();
Console.WriteLine("file: {0}\n", item.Name);
Console.WriteLine("Type: {0}\n", item.TypedObject.ToString());
if (item.TypedObject.ToString() == "Microsoft.SharePoint.Client.File") //To check if there is a better way to check if the item is a file
if (item.ServerObjectIsNull != true)
{
ctx.Load(item, i => i.ListItemAllFields);
ctx.ExecuteQuery();
var folder = ctx.Web.GetFolderByServerRelativeUrl((string)item.ListItemAllFields["FileDirRef"]);
ctx.Load(folder);
ctx.ExecuteQuery();
Console.WriteLine("parent relative url {0}\n", folder.ServerRelativeUrl);
return folder.ServerRelativeUrl;
}
return null;
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
return null;
}

lotus.domino.local.Item cannot be cast to lotus.domino.RichTextItem

I try to put a file into a richtext but it crashes !
In my first code, I try to use directly "getFirstItem", in first time it was ok but now i try to use it again and it crashed.
In second time i pass with an object and it find my obj doesn't an richtextItem (instanceof) ???
I don't understand.
I have the message : "lotus.domino.local.Item cannot be cast to lotus.domino.RichTextItem" ?
Could you help me ?
public void copieFichierDansRichText(String idDocument, String nomRti, File file,
String nameFichier, String chemin) throws NotesException {
lotus.domino.Session session = Utils.getSession();
lotus.domino.Database db = session.getCurrentDatabase();
lotus.domino.Document monDoc = db.getDocumentByUNID(idDocument);
lotus.domino.RichTextItem rtiNew = null;
try {
try {
if (monDoc != null) {
// if (monDoc.getFirstItem(nomRti) != null) {
// rtiNew = (lotus.domino.RichTextItem)
// monDoc.getFirstItem(nomRti);
// } else {
// rtiNew = (lotus.domino.RichTextItem)
// monDoc.createRichTextItem(nomRti);
// }
Object obj = null;
if (monDoc.getFirstItem(nomRti) != null) {
obj = monDoc.getFirstItem(nomRti);
if (obj instanceof lotus.domino.RichTextItem) {
rtiNew = (lotus.domino.RichTextItem) obj;
}
} else {
obj = monDoc.createRichTextItem(nomRti);
if (obj instanceof lotus.domino.RichTextItem) {
rtiNew = (lotus.domino.RichTextItem) obj;
}
}
PieceJointe pieceJointe = new PieceJointe();
pieceJointe = buildPieceJointe(file, nameFichier, chemin);
rtiNew.embedObject(EmbeddedObject.EMBED_ATTACHMENT, "", pieceJointe.getChemin()
+ pieceJointe.getNomPiece(), pieceJointe.getNomPiece());
monDoc.computeWithForm(true, false);
monDoc.save(true);
}
} finally {
rtiNew.recycle();
monDoc.recycle();
db.recycle();
session.recycle();
}
} catch (Exception e) {
e.printStackTrace();
}
}
EDIT : I try to modify my code with yours advices but the items never considerate as richtextitem. It is my problem. I don't understand why, because in my field it is a richtext ! For it, the item can't do :
rtiNew = (lotus.domino.RichTextItem) item1;
because item1 not be a richtext !!!
I was trying to take all the fields and pass in the item one by one, and it never go to the obj instance of lotus.domini.RichTextItem....
Vector items = doc.getItems();
for (int i=0; i<items.size(); i++) {
// get next element from the Vector (returns java.lang.Object)
Object obj = items.elementAt(i);
// is the item a RichTextItem?
if (obj instanceof RichTextItem) {
// yes it is - cast it as such // it never go here !!
rt = (RichTextItem)obj;
} else {
// nope - cast it as an Item
item = (Item)obj;
}
}
A couple of things. First of all I would set up a util class method to handle the object recycling in a neater way:
public enum DominoUtil {
;
public static void recycle(Base... bases) {
for (Base base : bases) {
if (base != null) {
try {
base.recycle();
} catch (Exception e) {
// Do nothing
}
}
}
}
}
Secondly I would remove the reduntants try/catch blocks and simplify it like this:
private void copieFichierDansRichText(String idDocument, String nomRti, File file,
String nameFichier, String chemin) {
Session session = DominoUtils.getCurrentSession();
Database db = session.getCurrentDatabase();
Document monDoc = null;
try {
monDoc = db.getDocumentByUNID(idDocument);
Item item = monDoc.getFirstItem(nomRti);
if (item == null) {
item = monDoc.createRichTextItem(nomRti);
} else if (item.getType() != Item.RICHTEXT) {
// The item is not a rich text item
// What are you going to do now?
}
RichTextItem rtItem = (RichTextItem) item;
PieceJointe pieceJointe = new PieceJointe();
pieceJointe = buildPieceJointe(file, nameFichier, chemin);
rtItem.embedObject(EmbeddedObject.EMBED_ATTACHMENT, "", pieceJointe.getChemin()
+ pieceJointe.getNomPiece(), pieceJointe.getNomPiece());
monDoc.computeWithForm(true, false);
monDoc.save(true);
} catch (NotesException e) {
throw new FacesException(e);
} finally {
DominoUtil.recycle(monDoc);
}
}
Finally, apart from the monDoc, you need not recycle anything else. Actually Session would be automatically recycled and anything beneath with it (so no need to recycle db, let alone the session!, good rule is don't recycle what you didn't instantiate), but it's not bad to keep the habit of keeping an eye on what you instantiate. If it were a loop with many documents you definitively want to do that. If you also worked with many items you would want to recycle them as early as possible. Anyway, considered the scope of the code it's sufficient like this. Obviously you would call DominoUtil.recycle directly from the try block. If you have multiple objects you can recycle them at once possibly by listing them in the reverse order you set them (eg. DominoUtil.recycle(item, doc, view)).
Also, what I think you miss is the check on the item in case it's not a RichTextItem - and therefore can't be cast. I put a comment where I think you should decide what to do before proceeding. If you let it like that and let the code proceed you will have the code throw an error. Always better to catch the lower level exception and re-throw a higher one (you don't want the end user to know more than it is necessary to know). In this case I went for the simplest thing: wrapped NotesException in a FacesException.

Activated Solution on Sharepoint 2010 is not visible

I have activated a WSP file which includes a website template. This works and I can see the solution int he solution gallery. When I try to create a website, based on that template, its not showing up. But it says "Status: Activated".
Then I tried to deactivate it and activate it again manually. Out of a sudden, there is a new template showing up, which takes the name of my template appended by a "2".
So whats happening here exactly? The code to activate my solution is:
System.IO.MemoryStream input = new System.IO.MemoryStream(System.IO.File.ReadAllBytes(rootDirectory + "\\Templates\\Project.wsp"), true);
SPDocumentLibrary solutionGallery = (SPDocumentLibrary)web.Site.GetCatalog(SPListTemplateType.SolutionCatalog);
try
{
SPFile solutionFile = solutionGallery.RootFolder.Files.Add("Project.wsp", input);
SPUserSolution newUserSolution = web.Site.Solutions.Add(solutionFile.Item.ID);
}
catch { ... }
Ok, I found the answer myself and want to share it here. The solution is, not to provide the solution in the catalog, but also to enable the features! It works like this:
System.IO.MemoryStream input = new System.IO.MemoryStream(System.IO.File.ReadAllBytes(rootDirectory + "\\Templates\\Project.wsp"), true);
SPDocumentLibrary solutionGallery = (SPDocumentLibrary)web.Site.GetCatalog(SPListTemplateType.SolutionCatalog);
try
{
SPFile solutionFile = solutionGallery.RootFolder.Files.Add("Project.wsp", input);
SPUserSolution newUserSolution = web.Site.Solutions.Add(solutionFile.Item.ID);
Guid solutionId = newUserSolution.SolutionId;
SPFeatureDefinitionCollection siteFeatures = web.Site.FeatureDefinitions;
var features = from SPFeatureDefinition f
in siteFeatures
where f.SolutionId.Equals(solutionId) && f.Scope == SPFeatureScope.Site
select f;
foreach (SPFeatureDefinition feature in features)
{
try
{
web.Site.Features.Add(feature.Id, false, SPFeatureDefinitionScope.Site);
}
catch { }
}
SPWebTemplateCollection webTemplates = web.Site.RootWeb.GetAvailableWebTemplates(1033);
SPWebTemplate webTemplate = (from SPWebTemplate t
in webTemplates
where t.Title == "Projekt"
select t).FirstOrDefault();
if (webTemplate != null)
{
try
{
web.Site.RootWeb.ApplyWebTemplate(webTemplate.Name);
}
catch { }
}
}
catch { ... }

Connect marker with EditPart

I have a graphical editor which extends GraphicalEditorWithFlyoutPalette.
There could be appear different markers, so it would be nice, if there is any possibility to connect the marker with the EditPart.
I think one possibility is to extend the TableViewer and the corresponding cell classes. But perhaps there is a better and more easier way.
I create my test markers like following:
IResource resource = (IResource) input.getAdapter(IResource.class);
try
{
IMarker marker = resource.createMarker(IMarker.PROBLEM);
marker.setAttribute(IMarker.TEXT, "text");
marker.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
marker.setAttribute(IMarker.MESSAGE, "message");
}
catch (CoreException e)
{
e.printStackTrace();
}
input is my IEditorInput.
In my first attempt, I was trying to extends the ExtendedMarkersView, which fails because it is an internal class.
Another way was to write the view and all corresponding stuff new, but it seems to be senseless.
So I found a work around based on https://stackoverflow.com/a/10501971/390177.
While creating the IMarker, I set additional attributes to link the corresponding data object. With the help of the object I can search for the AbstractGraphicalEditPart with the EditPartRegistry.
After that it is possible to create a selection on the EditPart and reveal to it.
#Override
public void selectionChanged(IWorkbenchPart part, ISelection selection) {
IStructuredSelection s = (IStructuredSelection) selection;
if (s.getFirstElement() instanceof MarkerItem) {
MarkerItem marker = (MarkerItem) s.getFirstElement();
if (marker != null && marker.getMarker() != null) {
IMarker iMarker = marker.getMarker();
AbstractGraphicalEditPart editPart = null;
DataObject object ...
editPart = (AbstractGraphicalEditPart) getGraphicalViewer().getEditPartRegistry().get(object);
if (editPart != null) {
StructuredSelection eSelection = new StructuredSelection(editPart);
getGraphicalViewer().setSelection(eSelection);
// once selected if you want to get it so the
// graphicalviewer scrolls to reveal the part on the
// screen
getGraphicalViewer().reveal(editPart);
}
}
} else {
super.selectionChanged(part, selection);
}
}

Resources