| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256 | // Copyright 1998-2017 Epic Games, Inc. All Rights Reserved.#pragma once#include "CoreMinimal.h"#include "IDocumentation.h"#include "Misc/Paths.h"#include "HAL/FileManager.h"#include "Internationalization/Culture.h"#include "UnrealEdMisc.h"#include "Interfaces/IPluginManager.h"#include "DocumentationDefines.h"namespace EXT_DOC_NAMESPACE{class FExtDocumentationLink{public: 	static FString GetUrlRoot(const FString& BaseUrlId = FString())	{		return IDocumentation::Get()->GetBaseUrl(BaseUrlId);	}	static FString GetHomeUrl()	{		return GetHomeUrl(FInternationalization::Get().GetCurrentCulture());	}	static FString GetHomeUrl(const FCultureRef& Culture)	{		FString Url;		FUnrealEdMisc::Get().GetURL( TEXT("UDNURL"), Url, true );		Url.ReplaceInline(TEXT("/INT/"), *FString::Printf(TEXT("/%s/"), *(Culture->GetUnrealLegacyThreeLetterISOLanguageName())));		return Url;	}	static FString ToUrl(const FString& Link, FDocumentationSourceInfo const& Source, const FString& BaseUrlId = FString())	{		return ToUrl(Link, FInternationalization::Get().GetCurrentCulture(), Source, BaseUrlId);	}	static FString ToUrl(const FString& Link, const FCultureRef& Culture, FDocumentationSourceInfo const& Source, const FString& BaseUrlId = FString())	{		// Get the base URL for this doc request, if any.		// It may have any or all of the following pieces in it.		FString UrlRoot = GetUrlRoot(BaseUrlId);		FString RootPath;		FString QueryString;		FString Anchor;		SplitLink(UrlRoot, RootPath, QueryString, Anchor);		// Break up the incoming documentation link into pieces.		// Depending on where it comes from, the link may be just a page ID, or it may have any or all		// of the following pieces in it. If there's a query string, SplitLink will merge it with the existing query		// string found in the base URL (if any). If there's an anchor, SplitLink will use it /instead/ of the		// one in the BaseUrl (if any).		FString LinkPath;		SplitLink(Link, LinkPath, QueryString, Anchor);		const FString TrimmedPartialPath = LinkPath.TrimChar('/');		// Add query parameters for the source, if needed.		AddSourceInfoToQueryString(QueryString, Source);		FString AssembledUrl = RootPath + QueryString + Anchor;		FUnrealEdMisc::Get().ReplaceDocumentationURLWildcards(AssembledUrl, Culture, TrimmedPartialPath);		return AssembledUrl;	}	static FString ToFilePath( const FString& Link )	{		FInternationalization& I18N = FInternationalization::Get();		FString FilePath = ToFilePath(Link, I18N.GetCurrentCulture());		if (!FPaths::FileExists(FilePath))		{			const FCulturePtr FallbackCulture = I18N.GetCulture(TEXT("en"));			if (FallbackCulture.IsValid())			{				const FString FallbackFilePath = ToFilePath(Link, FallbackCulture.ToSharedRef());				if (FPaths::FileExists(FallbackFilePath))				{					FilePath = FallbackFilePath;				}			}		}		return FilePath;	}	static FString ToFilePath(const FString& Link, const FCultureRef& Culture)	{		FString Path;		FString Anchor;		FString QueryString;		SplitLink(Link, Path, QueryString, Anchor);		const FString PartialPath = FString::Printf(TEXT("%s%s/index.html"), *(Culture->GetUnrealLegacyThreeLetterISOLanguageName()), *Path);		return FString::Printf(TEXT("%sDocumentation/HTML/%s"), *FPaths::ConvertRelativePathToFull(FPaths::EngineDir()), *PartialPath);	}	static FString ToFileUrl(const FString& Link, FDocumentationSourceInfo const& SourceInfo)	{		FInternationalization& I18N = FInternationalization::Get();		FCultureRef Culture = I18N.GetCurrentCulture();		FString FilePath = ToFilePath(Link, Culture);		if (!FPaths::FileExists(FilePath))		{			const FCulturePtr FallbackCulture = I18N.GetCulture(TEXT("en"));			if (FallbackCulture.IsValid())			{				const FString FallbackFilePath = ToFilePath(Link, FallbackCulture.ToSharedRef());				if (FPaths::FileExists(FallbackFilePath))				{					Culture = FallbackCulture.ToSharedRef();				}			}		}		return ToFileUrl(Link, Culture, SourceInfo);	}	static FString ToFileUrl(const FString& Link, const FCultureRef& Culture, FDocumentationSourceInfo const& SourceInfo)	{		FString Path;		FString Anchor;		FString QueryString;		SplitLink(Link, Path, QueryString, Anchor);		AddSourceInfoToQueryString(QueryString, SourceInfo);		return FString::Printf(TEXT("file:///%s%s%s"), *ToFilePath(Link, Culture), *QueryString, *Anchor);	}	static FString ToSourcePath(const FString& Link)	{		FInternationalization& I18N = FInternationalization::Get();		FString SourcePath = ToSourcePath(Link, I18N.GetCurrentCulture());		if (!FPaths::FileExists(SourcePath))		{			const FCulturePtr FallbackCulture = I18N.GetCulture(TEXT("en"));			if (FallbackCulture.IsValid())			{				const FString FallbackSourcePath = ToSourcePath(Link, FallbackCulture.ToSharedRef());				if (FPaths::FileExists(FallbackSourcePath))				{					SourcePath = FallbackSourcePath;				}			}		}		return SourcePath;	}	static FString ToSourcePath(const FString& Link, const FCultureRef& Culture)	{		FString Path;		FString Anchor;		FString QueryString;		SplitLink(Link, Path, QueryString, Anchor);		static FString DocumentationPath = IPluginManager::Get().FindPlugin(DocumentationHostPluginName)->GetBaseDir() / TEXT("Resources/Documentation/");		const FString FullDirectoryPath = DocumentationPath + TEXT( "Source" ) + Path + "/";		const FString WildCard = FString::Printf(TEXT("%s*.%s.udn"), *FullDirectoryPath, *(Culture->GetUnrealLegacyThreeLetterISOLanguageName()));		TArray<FString> Filenames;		IFileManager::Get().FindFiles(Filenames, *WildCard, true, false);		if (Filenames.Num() > 0)		{			return FullDirectoryPath + Filenames[0];		}		// Since the source file doesn't exist already make up a valid name for a new one		FString Category = FPaths::GetBaseFilename(Link);		return FString::Printf(TEXT("%s%s.%s.udn"), *FullDirectoryPath, *Category, *(Culture->GetUnrealLegacyThreeLetterISOLanguageName()));	}private:	static void AddSourceInfoToQueryString(FString& QueryString, FDocumentationSourceInfo const& Info)	{		if (Info.IsEmpty() == false)		{			if (QueryString.IsEmpty())			{				QueryString = FString::Printf(TEXT("?utm_source=%s&utm_medium=%s&utm_campaign=%s"), *Info.Source, *Info.Medium, *Info.Campaign);			}			else			{				QueryString = FString::Printf(TEXT("%s&utm_source=%s&utm_medium=%s&utm_campaign=%s"), *QueryString, *Info.Source, *Info.Medium, *Info.Campaign);			}		}	}		static void SplitLink( const FString& Link, /*OUT*/ FString& Path, /*OUT*/ FString& QueryString, /*OUT*/ FString& Anchor )	{		FString CleanedLink = Link;		CleanedLink.TrimStartAndEndInline();		if ( CleanedLink == TEXT("%ROOT%") )		{			Path.Empty();			Anchor.Empty();			QueryString.Empty();		}		else		{			FString PathAndQueryString;			if ( !CleanedLink.Split( TEXT("#"), &PathAndQueryString, &Anchor ) )			{				PathAndQueryString = CleanedLink;			}			else if ( !Anchor.IsEmpty() )			{				// ensure leading #				Anchor = FString( TEXT("#") ) + Anchor;			}			if ( Anchor.EndsWith( TEXT("/") ) )			{				Anchor = Anchor.Left( Anchor.Len() - 1 );			}			if ( PathAndQueryString.EndsWith( TEXT("/") ) )			{				PathAndQueryString = PathAndQueryString.Left(PathAndQueryString.Len() - 1);			}			if ( !PathAndQueryString.IsEmpty() && !PathAndQueryString.StartsWith( TEXT("/") ) )			{				PathAndQueryString = FString(TEXT("/")) + PathAndQueryString;			}			// split path and query string			if (!PathAndQueryString.Split(TEXT("?"), &Path, &QueryString))			{				Path = PathAndQueryString;			}			else if (!QueryString.IsEmpty())			{				// ensure leading ?				QueryString = FString(TEXT("?")) + QueryString;			}		}	}};}
 |