Skip to content

Commit 4ae850b

Browse files
authored
LT-21996: Don’t create a link when there is no target (#353)
* LT-21996: Don’t create a link when there is no target Regardless of whether we are generating an entry for viewing in Flex or for exporting, use the same rules to determine if links to other entries should be created. If the target entry is not displayed then don’t generate a link (Guid).
1 parent 784339e commit 4ae850b

3 files changed

Lines changed: 132 additions & 41 deletions

File tree

Src/xWorks/ConfiguredLcmGenerator.cs

Lines changed: 94 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,22 @@ internal static string GetWsForEntryType(ICmObject entry, LcmCache cache)
249249
return wsString;
250250
}
251251

252+
/// <summary>
253+
/// Get the ConfigurableDictionaryNode for the main entry.
254+
/// </summary>
255+
private static ConfigurableDictionaryNode MainEntryNode(DictionaryConfigurationModel configuration)
256+
{
257+
return configuration.Parts[0];
258+
}
259+
260+
/// <summary>
261+
/// Get the ConfigurableDictionaryNode for the minor entry.
262+
/// </summary>
263+
private static ConfigurableDictionaryNode MinorEntryNode(ICmObject entry, DictionaryConfigurationModel configuration)
264+
{
265+
return configuration.Parts.Skip(1).LastOrDefault(part => IsListItemSelectedForExport(part, entry));
266+
}
267+
252268
/// <summary>
253269
/// Generating the xhtml representation for the given ICmObject using the given configuration node to select which data to write out
254270
/// If it is a Dictionary Main Entry or non-Dictionary entry, uses the first configuration node.
@@ -259,7 +275,7 @@ public static IFragment GenerateContentForEntry(ICmObject entryObj, DictionaryCo
259275
DictionaryPublicationDecorator publicationDecorator, GeneratorSettings settings, int index = -1)
260276
{
261277
if (IsMainEntry(entryObj, configuration))
262-
return GenerateContentForMainEntry(entryObj, configuration.Parts[0], publicationDecorator, settings, index);
278+
return GenerateContentForMainEntry(entryObj, MainEntryNode(configuration), publicationDecorator, settings, index);
263279

264280
var entry = (ILexEntry)entryObj;
265281
return entry.PublishAsMinorEntry
@@ -279,7 +295,7 @@ private static IFragment GenerateContentForMinorEntry(ICmObject entry, Dictionar
279295
DictionaryPublicationDecorator publicationDecorator, GeneratorSettings settings, int index)
280296
{
281297
// LT-15232: show minor entries using only the last applicable Minor Entry node (not more than once)
282-
var applicablePart = configuration.Parts.Skip(1).LastOrDefault(part => IsListItemSelectedForExport(part, entry));
298+
var applicablePart = MinorEntryNode(entry, configuration);
283299
return applicablePart == null ? settings.ContentGenerator.CreateFragment() : GenerateContentForEntry(entry, applicablePart, publicationDecorator, settings, index);
284300
}
285301

@@ -300,6 +316,61 @@ internal static bool IsMainEntry(ICmObject entry, DictionaryConfigurationModel c
300316
return lexEntry.EntryRefsOS.Any(ler => ler.RefType == LexEntryRefTags.krtComplexForm);
301317
}
302318

319+
/// <summary>
320+
/// Checks if a lexical entry is displayed.
321+
/// </summary>
322+
/// <returns>true if displayed.</returns>
323+
private static bool EntryIsDisplayed(ILexEntry lexEntry, List<ConfigurableDictionaryNode> nodeList,
324+
DictionaryPublicationDecorator publicationDecorator, GeneratorSettings settings)
325+
{
326+
// If there is no publication decorator then we are generating a preview. For previews always
327+
// treat a target as displayed.
328+
if (publicationDecorator == null)
329+
{
330+
return true;
331+
}
332+
333+
bool displayed = false;
334+
DictionaryConfigurationModel configModel = nodeList.First().Model;
335+
bool mainEntry = IsMainEntry(lexEntry, configModel);
336+
337+
// First determine if the dictionary configuration is set to display the entry type.
338+
if (mainEntry)
339+
{
340+
displayed = MainEntryNode(configModel).IsEnabled;
341+
}
342+
else
343+
{
344+
var node = MinorEntryNode(lexEntry, configModel);
345+
displayed = node != null && node.IsEnabled;
346+
}
347+
348+
// Second check if we are publishing minor entries.
349+
if (displayed && !mainEntry && !lexEntry.PublishAsMinorEntry)
350+
{
351+
displayed = false;
352+
}
353+
354+
// Third check if the active Publication excludes it.
355+
var currentPubPoss = publicationDecorator.Publication;
356+
if (displayed && currentPubPoss != null &&
357+
currentPubPoss.NameHierarchyString != xWorksStrings.AllEntriesPublication)
358+
{
359+
if (!lexEntry.PublishIn.Contains(currentPubPoss))
360+
{
361+
displayed = false;
362+
}
363+
// Note: A better name for ShowMainEntryIn() would probably be
364+
// ShowAsHeadwordIn(), since it applies to both main and minor entries.
365+
if (!lexEntry.ShowMainEntryIn.Contains(currentPubPoss))
366+
{
367+
displayed = false;
368+
}
369+
}
370+
371+
return displayed;
372+
}
373+
303374
/// <summary>Generates content with the GeneratorSettings.ContentGenerator for an ICmObject for a specific ConfigurableDictionaryNode</summary>
304375
/// <remarks>the configuration node must match the entry type</remarks>
305376
internal static IFragment GenerateContentForEntry(ICmObject entry, ConfigurableDictionaryNode configuration,
@@ -585,7 +656,7 @@ internal static IFragment GenerateContentForFieldByReflection(object field, List
585656
return settings.ContentGenerator.CreateFragment();
586657
}
587658

588-
var bldr = GenerateContentForValue(field, propertyValue, nodeList, settings);
659+
var bldr = GenerateContentForValue(field, propertyValue, nodeList, publicationDecorator, settings);
589660
if (config.ReferencedOrDirectChildren != null)
590661
{
591662
foreach (var child in config.ReferencedOrDirectChildren)
@@ -2549,48 +2620,40 @@ private static bool IsCollectionEmpty(object collection)
25492620
/// <param name="config"></param>
25502621
/// <param name="settings"></param>
25512622
private static IFragment GenerateContentForValue(object field, object propertyValue, List<ConfigurableDictionaryNode> nodeList,
2552-
GeneratorSettings settings)
2623+
DictionaryPublicationDecorator publicationDecorator, GeneratorSettings settings)
25532624
{
25542625
// If we're working with a headword, either for this entry or another one (Variant or Complex Form, etc.), store that entry's GUID
25552626
// so we can generate a link to the main or minor entry for this headword.
25562627
var guid = Guid.Empty;
25572628
var config = nodeList.Last();
25582629
if (config.IsHeadWord)
25592630
{
2560-
if (field is ILexEntry)
2631+
ILexEntry lexEntry = null;
2632+
if (field is ILexEntry entry)
25612633
{
2562-
// For Complex Forms, don't generate the reference if we are not going to publish the entry to Webonary.
2563-
if (settings.IsWebExport &&
2564-
!((ILexEntry)field).PublishAsMinorEntry &&
2565-
((ILexEntry)field).EntryRefsOS.Count > 0)
2566-
{
2567-
guid = Guid.Empty;
2568-
}
2569-
else
2570-
{
2571-
guid = ((ILexEntry)field).Guid;
2572-
}
2634+
lexEntry = entry;
25732635
}
2574-
else if (field is ILexEntryRef)
2636+
else if (field is ILexEntryRef entryRef)
25752637
{
2576-
// For Variants, don't generate the reference if we are not going to publish the entry to Webonary.
2577-
if (settings.IsWebExport &&
2578-
!((ILexEntryRef)field).OwningEntry.PublishAsMinorEntry)
2579-
{
2580-
guid = Guid.Empty;
2581-
}
2582-
else
2583-
{
2584-
guid = ((ILexEntryRef)field).OwningEntry.Guid;
2585-
}
2638+
lexEntry = entryRef.OwningEntry;
2639+
}
2640+
else if (field is ISenseOrEntry senseOrEntry)
2641+
{
2642+
lexEntry = senseOrEntry.Item is ILexEntry ? (ILexEntry)(senseOrEntry.Item) : ((ILexSense)(senseOrEntry.Item)).Entry;
2643+
}
2644+
else if (field is ILexSense sense)
2645+
{
2646+
lexEntry = sense.OwnerOfClass(LexEntryTags.kClassId) as ILexEntry;
25862647
}
2587-
else if (field is ISenseOrEntry)
2588-
guid = ((ISenseOrEntry)field).EntryGuid;
2589-
else if (field is ILexSense)
2590-
guid = ((ILexSense)field).OwnerOfClass(LexEntryTags.kClassId).Guid;
25912648
else
25922649
Debug.WriteLine(String.Format("Need to find Entry Guid for {0}",
25932650
field == null ? DictionaryConfigurationMigrator.BuildPathStringFromNode(config) : field.GetType().Name));
2651+
2652+
// Check if the Lexical Entry is going to be displayed.
2653+
if (lexEntry != null && EntryIsDisplayed(lexEntry, nodeList, publicationDecorator, settings))
2654+
{
2655+
guid = lexEntry.Guid;
2656+
}
25942657
}
25952658

25962659
if (propertyValue is ITsString)

Src/xWorks/xWorksTests/ConfiguredXHTMLGeneratorTests.cs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7418,19 +7418,23 @@ public void GenerateContentForEntry_ComplexFormDontGenerateReference()
74187418
};
74197419
CssGeneratorTests.PopulateFieldsForTesting(mainEntryNode);
74207420

7421+
mainEntryNode.Model.IsRootBased = true;
74217422
subentryRef.HideMinorEntry = 1;
74227423
const string withReference = "/div[@class='lexentry']/span[@class='subentries']/span[@class='subentry']/span[@class='headword']/span[@lang='fr']/span[@lang='fr']/a[@href]";
74237424
const string withoutReference = "/div[@class='lexentry']/span[@class='subentries']/span[@class='subentry']/span[@class='headword']/span[@lang='fr']/span[@lang='fr']";
74247425

7425-
// When hiding minor entries this should still generate the reference (if not publishing to Webonary).
7426+
// When hiding minor entries and NOT publishing to Webonary this should NOT generate the reference.
74267427
var settings = new ConfiguredLcmGenerator.GeneratorSettings(Cache, m_propertyTable, false, false, null, false, false);
7427-
var result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, mainEntryNode, null, settings).ToString();
7428-
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withReference, 2);
7428+
var flidVirtual = Cache.ServiceLocator.GetInstance<Virtuals>().LexDbEntries;
7429+
var pubEverything = new DictionaryPublicationDecorator(Cache, (ISilDataAccessManaged)Cache.MainCacheAccessor, flidVirtual);
7430+
var result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, mainEntryNode, pubEverything, settings).ToString();
7431+
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withReference, 0);
7432+
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withoutReference, 2);
74297433

74307434
//SUT
74317435
// When hiding minor entries and publishing to Webonary this should NOT generate the reference.
74327436
settings = new ConfiguredLcmGenerator.GeneratorSettings(Cache, m_propertyTable, false, false, null, false, true);
7433-
result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, mainEntryNode, null, settings).ToString();
7437+
result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, mainEntryNode, pubEverything, settings).ToString();
74347438
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withReference, 0);
74357439
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withoutReference, 2);
74367440
}
@@ -7687,19 +7691,23 @@ public void GenerateContentForEntry_VariantDontGenerateReference()
76877691
};
76887692
CssGeneratorTests.PopulateFieldsForTesting(model);
76897693

7694+
mainEntryNode.Model.IsRootBased = true;
76907695
variantEntryRef.HideMinorEntry = 1;
76917696
const string withReference = "/div[@class='lexentry']/span[@class='variantformentrybackrefs']/span[@class='variantformentrybackref']/span[@class='headword']/span[@lang='fr']/span[@lang='fr']/a[@href]";
76927697
const string withoutReference = "/div[@class='lexentry']/span[@class='variantformentrybackrefs']/span[@class='variantformentrybackref']/span[@class='headword']/span[@lang='fr']/span[@lang='fr']";
76937698

7694-
// When hiding minor entries this should still generate the reference (if not publishing to Webonary).
7699+
// When hiding minor entries and NOT publishing to Webonary this should NOT generate the reference.
76957700
var settings = new ConfiguredLcmGenerator.GeneratorSettings(Cache, m_propertyTable, false, false, null, false, false);
7696-
var result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, model, null, settings).ToString();
7697-
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withReference, 2);
7701+
var flidVirtual = Cache.ServiceLocator.GetInstance<Virtuals>().LexDbEntries;
7702+
var pubEverything = new DictionaryPublicationDecorator(Cache, (ISilDataAccessManaged)Cache.MainCacheAccessor, flidVirtual);
7703+
var result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, model, pubEverything, settings).ToString();
7704+
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withReference, 0);
7705+
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withoutReference, 2);
76987706

76997707
//SUT
77007708
// When hiding minor entries and publishing to Webonary this should NOT generate the reference.
77017709
settings = new ConfiguredLcmGenerator.GeneratorSettings(Cache, m_propertyTable, false, false, null, false, true);
7702-
result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, model, null, settings).ToString();
7710+
result = ConfiguredLcmGenerator.GenerateContentForEntry(lexentry, model, pubEverything, settings).ToString();
77037711
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withReference, 0);
77047712
AssertThatXmlIn.String(result).HasSpecifiedNumberOfMatchesForXpath(withoutReference, 2);
77057713
}

Src/xWorks/xWorksTests/LcmJsonGeneratorTests.cs

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -507,7 +507,17 @@ public void GenerateJsonForEntry_FilterByPublication()
507507
Children = new List<ConfigurableDictionaryNode> { mainHeadwordNode, mainPronunciationsNode, sensesNode, pictureNode, subentryNode, variantNode },
508508
FieldDescription = "LexEntry"
509509
};
510-
CssGeneratorTests.PopulateFieldsForTesting(mainEntryNode);
510+
var minorEntryNode = new ConfigurableDictionaryNode
511+
{
512+
FieldDescription = "LexEntry",
513+
CSSClassNameOverride = "minorentry",
514+
DictionaryNodeOptions = ConfiguredXHTMLGeneratorTests.GetFullyEnabledListOptions(DictionaryNodeListOptions.ListIds.Variant, Cache)
515+
};
516+
var model = new DictionaryConfigurationModel
517+
{
518+
Parts = new List<ConfigurableDictionaryNode> { mainEntryNode, minorEntryNode }
519+
};
520+
CssGeneratorTests.PopulateFieldsForTesting(model);
511521

512522
//SUT
513523
var output = ConfiguredLcmGenerator.GenerateContentForEntry(entryEntry, mainEntryNode, pubMain, DefaultSettings, 0).ToString();
@@ -577,7 +587,17 @@ public void GenerateJsonForEntry_TypeAfterForm()
577587
Children = new List<ConfigurableDictionaryNode> { mainHeadwordNode, variantNodeTypeAfter },
578588
FieldDescription = "LexEntry"
579589
};
580-
CssGeneratorTests.PopulateFieldsForTesting(mainEntryNodeTypeAfter);
590+
var minorEntryNode = new ConfigurableDictionaryNode
591+
{
592+
FieldDescription = "LexEntry",
593+
CSSClassNameOverride = "minorentry",
594+
DictionaryNodeOptions = ConfiguredXHTMLGeneratorTests.GetFullyEnabledListOptions(DictionaryNodeListOptions.ListIds.Variant, Cache)
595+
};
596+
var model = new DictionaryConfigurationModel
597+
{
598+
Parts = new List<ConfigurableDictionaryNode> { mainEntryNodeTypeAfter, minorEntryNode }
599+
};
600+
CssGeneratorTests.PopulateFieldsForTesting(model);
581601

582602
//SUT
583603
var outputTypeAfter = ConfiguredLcmGenerator.GenerateContentForEntry(entryEntry, mainEntryNodeTypeAfter, pubMain, DefaultSettings, 0).ToString();

0 commit comments

Comments
 (0)