*
*/
namespace ComboStrap;
use ComboStrap\Meta\Field\PageTemplateName;
use ComboStrap\Meta\Field\Region;
use ComboStrap\Web\Url;
use ComboStrap\Web\UrlRewrite;
use Exception;
class Site
{
const STRAP_TEMPLATE_NAME = "strap";
const SVG_LOGO_IDS = array(
'wiki:logo.svg',
'logo.svg'
);
const PNG_LOGO_IDS = array(
'logo.png',
'wiki:logo.png',
'favicon-32×32.png',
'favicon-16×16.png',
'apple-touch-icon.png',
'android-chrome-192x192.png'
);
/**
* Name of the main header slot
*/
public const SLOT_MAIN_HEADER_NAME = "slot_main_header";
/**
* Name of the main footer slot
*/
public const SLOT_MAIN_FOOTER_NAME = "slot_main_footer";
public const SLOT_MAIN_SIDE_NAME = "slot_main_side";
const CANONICAL = "configuration";
/**
* Strap Template meta (version, release date, ...)
* @var array
*/
private static $STRAP_TEMPLATE_INFO;
private $executingContext;
private $config;
/**
* @param ExecutionContext $executingContext
*/
public function __construct(ExecutionContext $executingContext)
{
$this->executingContext = $executingContext;
}
/**
* @return WikiPath[]
*/
public static function getLogoImagesAsPath(): array
{
$logosPaths = PluginUtility::mergeAttributes(self::PNG_LOGO_IDS, self::SVG_LOGO_IDS);
$logos = [];
foreach ($logosPaths as $logoPath) {
$dokuPath = WikiPath::createMediaPathFromId($logoPath);
if (FileSystems::exists($dokuPath)) {
try {
$logos[] = $dokuPath;
} catch (Exception $e) {
// The image is not valid
LogUtility::msg("The logo ($logoPath) is not a valid image. {$e->getMessage()}");
}
}
}
return $logos;
}
/**
* @deprecated see {@link SiteConfig::setUrlRewriteToDoku()}
*/
public static function setUrlRewriteToDoku()
{
ExecutionContext::getActualOrCreateFromEnv()->getConfig()
->setUrlRewriteToDoku();
}
/**
* Web server rewrite (Apache rewrite (htaccess), Nginx)
* @deprecated see {@link SiteConfig::setUrlRewriteToWebServer()}
*/
public static function setUrlRewriteToWebServer()
{
ExecutionContext::getActualOrCreateFromEnv()->getConfig()
->setUrlRewriteToWebServer();
}
/**
* https://www.dokuwiki.org/config:useslash
* @return void
*/
public static function useSlashSeparatorInEndpointUrl()
{
global $conf;
$conf['useslash'] = 1; // use slash instead of ;
}
public static function getUrlEndpointSeparator(): string
{
$defaultSeparator = WikiPath::NAMESPACE_SEPARATOR_DOUBLE_POINT;
$slashSeparator = "/";
global $conf;
$key = 'useslash';
$value = $conf[$key];
try {
$valueInt = DataType::toInteger($value);
} catch (ExceptionBadArgument $e) {
LogUtility::internalError("The ($key) configuration does not have an integer value ($value). Default separator returned");
return $defaultSeparator;
}
switch ($valueInt) {
case 0:
return $defaultSeparator;
case 1:
return $slashSeparator;
default:
LogUtility::internalError("The ($key) configuration has an integer value ($valueInt) that is not a valid one (0 or 1). Default separator returned");
return $defaultSeparator;
}
}
public static function getTocMinHeadings(): int
{
global $conf;
$confKey = 'tocminheads';
$tocMinHeads = $conf[$confKey];
if ($tocMinHeads === null) {
return 0;
}
try {
return DataType::toInteger($tocMinHeads);
} catch (ExceptionBadArgument $e) {
LogUtility::error("The configuration ($confKey) is not an integer. Error:{$e->getMessage()}", self::CANONICAL);
return 0;
}
}
/**
* @param int $int
* @deprecated
*/
public static function setTocMinHeading(int $int)
{
ExecutionContext::getActualOrCreateFromEnv()
->getConfig()
->setTocMinHeading($int);
}
public static function getTopTocLevel(): int
{
global $conf;
$confKey = 'toptoclevel';
$value = $conf[$confKey];
try {
return DataType::toInteger($value);
} catch (ExceptionBadArgument $e) {
LogUtility::error("The configuration ($confKey) has a value ($value) that is not an integer", self::CANONICAL);
return 1;
}
}
/**
* @param int $int
* @return void
* @deprecated
*/
public static function setTocTopLevel(int $int)
{
ExecutionContext::getActualOrCreateFromEnv()
->getConfig()
->setTocTopLevel($int);
}
/**
* @return int
* https://www.dokuwiki.org/config:breadcrumbs
*/
public static function getVisitedPagesCountInHistoricalBreadCrumb(): int
{
global $conf;
$confKey = 'breadcrumbs';
$visitedPagesInBreadCrumb = $conf[$confKey];
$defaultReturnValue = 10;
if ($visitedPagesInBreadCrumb === null) {
return $defaultReturnValue;
}
try {
return DataType::toInteger($visitedPagesInBreadCrumb);
} catch (ExceptionBadArgument $e) {
LogUtility::error("The configuration ($confKey) has value ($visitedPagesInBreadCrumb) that is not an integer. Error:{$e->getMessage()}");
return $defaultReturnValue;
}
}
/**
* This setting enables the standard DokuWiki XHTML renderer to be replaced by a render plugin that also provides XHTML output.
* @param string $string
* @return void
*/
public static function setXhtmlRenderer(string $string)
{
global $conf;
$conf["renderer_xhtml"] = $string;
}
/**
* The host of the actual server
* (may be virtual)
* @return string
*/
public static function getServerHost(): string
{
/**
* Based on {@link getBaseURL()}
* to be dokuwiki compliant
*/
$remoteHost = $_SERVER['HTTP_HOST'];
if ($remoteHost !== null) {
return $remoteHost;
}
$remoteHost = $_SERVER['SERVER_NAME'];
if ($remoteHost !== null) {
return $remoteHost;
}
/**
* OS name
*/
return php_uname('n');
}
public static function getLangDirection()
{
global $lang;
return $lang['direction'];
}
/**
* Set a site configuration outside a {@link ExecutionContext}
* It permits to configure the installation before execution
*
* For instance, we set the {@link PageTemplateName::CONF_DEFAULT_NAME default page layout} as {@link PageTemplateName::BLANK_TEMPLATE_VALUE}
* in test by default to speed ud test. In a normal environment, the default is {@link PageTemplateName::HOLY_TEMPLATE_VALUE}
*
* @param $key
* @param $value
* @param string|null $namespace - the plugin name
* @return void
* @deprecated use {@link SiteConfig::setConf()}
*/
public static function setConf($key, $value, ?string $namespace = PluginUtility::PLUGIN_BASE_NAME)
{
global $conf;
if ($namespace !== null) {
$conf['plugin'][$namespace][$key] = $value;
} else {
$conf[$key] = $value;
}
}
public static function getLangObject(): Lang
{
return Lang::createFromValue(Site::getLang());
}
public static function getOldDirectory(): LocalPath
{
global $conf;
/**
* Data dir is the pages dir (savedir is the data dir)
*/
$oldDirConf = $conf['olddir'];
if ($oldDirConf === null) {
throw new ExceptionRuntime("The old directory ($oldDirConf) is null");
}
return LocalPath::createFromPathString($oldDirConf);
}
function getEmailObfuscationConfiguration()
{
global $conf;
return $conf['mailguard'];
}
/**
* @return string|null
*/
public static function getLogoUrlAsSvg(): ?string
{
$url = null;
foreach (self::SVG_LOGO_IDS as $svgLogo) {
$svgLogoFN = mediaFN($svgLogo);
if (file_exists($svgLogoFN)) {
$url = ml($svgLogo, '', true, '', true);
break;
}
}
return $url;
}
/**
* @throws ExceptionNotFound
*/
public static function getLogoAsSvgImage(): WikiPath
{
foreach (self::SVG_LOGO_IDS as $svgLogo) {
$image = WikiPath::createMediaPathFromId($svgLogo);
if (FileSystems::exists($image)) {
return $image;
}
}
throw new ExceptionNotFound("No Svg Logo Image found");
}
/**
* @throws ExceptionNotFound
*/
public static function getLogoAsRasterImage(): FetcherRaster
{
foreach (self::PNG_LOGO_IDS as $pngLogo) {
$pngLogoPath = WikiPath::createMediaPathFromId($pngLogo);
if (!FileSystems::exists($pngLogoPath)) {
continue;
}
try {
return FetcherRaster::createImageRasterFetchFromPath($pngLogoPath);
} catch (ExceptionCompile $e) {
LogUtility::error("Error while getting the log as raster image: The png logo ($pngLogo) returns an error. {$e->getMessage()}", self::CANONICAL, $e);
continue;
}
}
throw new ExceptionNotFound("No raster logo image was found");
}
public static function getLogoUrlAsPng(): ?string
{
$url = null;
foreach (self::PNG_LOGO_IDS as $pngId) {
$svgLogoFN = mediaFN($pngId);
if (file_exists($svgLogoFN)) {
try {
$url = FetcherRaster::createImageRasterFetchFromId($pngId)
->getFetchUrl()
->toAbsoluteUrl()
->toHtmlString();
} catch (ExceptionBadArgument|ExceptionBadSyntax|ExceptionNotExists $e) {
LogUtility::internalError("Hardcoded id should not give an error for the png logo url", self::CANONICAL, $e);
continue;
}
break;
};
}
return $url;
}
/**
* @return mixed
* @deprecated use {@link Site::getName()} instead
* https://www.dokuwiki.org/config:title
*/
public static function getTitle()
{
global $conf;
return $conf['title'];
}
/**
* https://www.dokuwiki.org/config:title
*/
public static function setName($name)
{
global $conf;
$conf['title'] = $name;
}
/**
* @param string $sep - the separator - generally ("-") but not always
* @return string
*
* Locale always canonicalizes to upper case.
*/
public static function getLocale(string $sep = "-"): string
{
$locale = null;
$lang = self::getLang();
$country = self::getLanguageRegion();
$locale = strtolower($lang) . $sep . strtoupper($country);
return $locale;
}
/**
*
* ISO 3166 alpha-2 country code
*
*/
public static function getLanguageRegion(): string
{
$region = SiteConfig::getConfValue(Region::CONF_SITE_LANGUAGE_REGION);
if (!empty($region)) {
return $region;
} else {
if (extension_loaded("intl")) {
$locale = locale_get_default();
$localeParts = explode("_", $locale, 2);
if (sizeof($localeParts) === 2) {
return $localeParts[1];
}
}
}
return "us";
}
/**
* @return string
* Wrapper around https://www.dokuwiki.org/config:lang
*/
public static function getLang(): string
{
global $conf;
$lang = $conf['lang'];
if ($lang === null) {
return "en";
}
return $lang;
}
/**
* In a {@link PluginUtility::isDevOrTest()} dev environment,
* don't set the
* https://www.dokuwiki.org/config:baseurl
* to be able to test the metadata / social integration
* via a tunnel
*
*/
public static function getBaseUrl(): string
{
/**
* Same as {@link getBaseURL()} ??
*/
global $conf;
$baseUrl = $conf['baseurl'];
if (!empty($baseUrl)) {
return $baseUrl;
}
return DOKU_URL;
}
public static function getTag()
{
global $conf;
return $conf['tag'] ?? null;
}
public static function setTemplate($template)
{
global $conf;
$conf['template'] = $template;
}
/**
* @return void
* @deprecated
*/
public static function setCacheXhtmlOn()
{
// ensure the value is not -1, which disables caching
// https://www.dokuwiki.org/config:cachetime
global $conf;
$conf['cachetime'] = 60 * 60;
}
public static function debugIsOn()
{
global $conf;
return $conf['allowdebug'];
}
public static function setCacheDefault()
{
// The value is -1, which disables caching
// https://www.dokuwiki.org/config:cachetime
global $conf;
$conf['cachetime'] = -1;
}
public static function useHeadingAsTitle()
{
// https://www.dokuwiki.org/config:useheading
global $conf;
$conf['useheading'] = 1;
}
public static function useHeadingDefault()
{
// https://www.dokuwiki.org/config:useheading
global $conf;
$conf['useheading'] = 0;
}
public static function getTemplate()
{
global $conf;
return $conf['template'];
}
public static function isStrapTemplate()
{
global $conf;
return $conf['template'] == self::STRAP_TEMPLATE_NAME;
}
public static function getPageDirectory(): LocalPath
{
global $conf;
/**
* Data dir is the pages dir (savedir is the data dir)
*/
$pageDirectory = $conf['datadir'];
if ($pageDirectory === null) {
throw new ExceptionRuntime("The page directory ($pageDirectory) is null");
}
return LocalPath::createFromPathString($pageDirectory);
}
public static function disableHeadingSectionEditing()
{
ExecutionContext::getActualOrCreateFromEnv()
->getConfig()
->setDisableHeadingSectionEditing();
}
public static function setBreadCrumbOn()
{
global $conf;
$conf['youarehere'] = 1;
}
public static function isHtmlRenderCacheOn(): bool
{
return ExecutionContext::getActualOrCreateFromEnv()
->getConfig()
->isXhtmlCacheOn();
}
/**
* @return LocalPath
* @deprecated
*/
public static function getDataDirectory(): LocalPath
{
return ExecutionContext::getActualOrCreateFromEnv()->getConfig()->getDataDirectory();
}
public static function isLowQualityProtectionEnable(): bool
{
return SiteConfig::getConfValue(LowQualityPage::CONF_LOW_QUALITY_PAGE_PROTECTION_ENABLE) === 1;
}
/**
* @return string
* @deprecated
*/
public static function getIndexPageName()
{
return ExecutionContext::getActualOrCreateFromEnv()->getConfig()->getIndexPageName();
}
/**
* @return mixed - Application / Website name
*/
public static function getName()
{
return self::getTitle();
}
public static function getTagLine()
{
global $conf;
return $conf['tagline'];
}
/**
* @return int
*/
public static function getXhtmlCacheTime(): int
{
global $conf;
$cacheTime = $conf['cachetime'];
if ($cacheTime === null) {
LogUtility::internalError("The global `cachetime` configuration was not set.", self::CANONICAL);
return FetcherMarkup::MAX_CACHE_AGE;
}
try {
return DataType::toInteger($cacheTime);
} catch (ExceptionBadArgument $e) {
LogUtility::error("The global `cachetime` configuration has a value ($cacheTime) that is not an integer. Error: {$e->getMessage()}", self::CANONICAL);
return FetcherMarkup::MAX_CACHE_AGE;
}
}
/**
* Absolute vs Relative URL
* https://www.dokuwiki.org/config:canonical
*/
public static function shouldUrlBeAbsolute(): bool
{
global $conf;
$value = $conf['canonical'];
if ($value === 1) {
return true;
}
return false;
}
/**
* @param string $description
* Same as {@link Site::setDescription()}
*/
public static function setTagLine(string $description)
{
global $conf;
$conf['tagline'] = $description;
}
/**
* @param string $description
*
*/
public static function setDescription(string $description)
{
self::setTagLine($description);
}
/**
* @param string $primaryColorValue
* @return void
* @deprecated
*/
public static function setPrimaryColor(string $primaryColorValue)
{
ExecutionContext::getActualOrCreateFromEnv()
->getConfig()
->setPrimaryColor($primaryColorValue);
}
/**
* @param $default
* @return ColorRgb|null
* @deprecated use {@link SiteConfig::getPrimaryColor()} instead
*/
public static function getPrimaryColor(string $default = null): ?ColorRgb
{
try {
return ExecutionContext::getActualOrCreateFromEnv()
->getConfig()
->getPrimaryColor();
} catch (ExceptionNotFound $e) {
if ($default === null) {
return null;
}
try {
return ColorRgb::createFromString($default);
} catch (ExceptionBadArgument $e) {
LogUtility::internalError("The value ($default) is not a valid color");
return null;
}
}
}
public static function getSecondaryColor($default = null): ?ColorRgb
{
$value = Site::getSecondaryColorValue($default);
if ($value === null) {
return null;
}
try {
return ColorRgb::createFromString($value);
} catch (ExceptionCompile $e) {
LogUtility::msg("The secondary color value configuration ($value) is not valid. Error: {$e->getMessage()}");
return null;
}
}
public static function setSecondaryColor(string $secondaryColorValue)
{
self::setConf(ColorRgb::SECONDARY_COLOR_CONF, $secondaryColorValue);
}
public static function unsetPrimaryColor()
{
self::setConf(BrandingColors::PRIMARY_COLOR_CONF, null);
}
/**
* @return bool
* @deprecated
*/
public static function isBrandingColorInheritanceEnabled(): bool
{
return ExecutionContext::getActualOrCreateFromEnv()->getConfig()->isBrandingColorInheritanceEnabled();
}
/**
* @param $default
* @return string|null
*/
public static function getPrimaryColorValue($default = null): ?string
{
$value = SiteConfig::getConfValue(BrandingColors::PRIMARY_COLOR_CONF, $default);
if ($value !== null && trim($value) !== "") {
return $value;
}
if (PluginUtility::isTest()) {
// too much trouble
// the load of styles is not consistent
return null;
}
$styles = ColorRgb::getDokuWikiStyles();
return $styles["replacements"]["__theme_color__"];
}
public static function getSecondaryColorValue($default = null)
{
$value = SiteConfig::getConfValue(ColorRgb::SECONDARY_COLOR_CONF, $default);
if ($value === null || trim($value) === "") {
return null;
}
return $value;
}
public static function setCanonicalUrlType(string $value)
{
self::setConf(PageUrlType::CONF_CANONICAL_URL_TYPE, $value);
}
public static function setCanonicalUrlTypeToDefault()
{
self::setConf(PageUrlType::CONF_CANONICAL_URL_TYPE, null);
}
public static function isBrandingColorInheritanceFunctional(): bool
{
return self::isBrandingColorInheritanceEnabled() && Site::getPrimaryColorValue() !== null;
}
public static function getMediaDirectory(): LocalPath
{
global $conf;
$mediaDirectory = $conf['mediadir'];
if ($mediaDirectory === null) {
throw new ExceptionRuntime("The media directory ($mediaDirectory) is null");
}
return LocalPath::createFromPathString($mediaDirectory);
}
public static function getCacheDirectory(): LocalPath
{
global $conf;
$cacheDirectory = $conf['cachedir'];
if ($cacheDirectory === null) {
throw new ExceptionRuntime("The cache directory ($cacheDirectory) is null");
}
return LocalPath::createFromPathString($cacheDirectory);
}
/**
* @throws ExceptionCompile
*/
private static function checkTemplateVersion()
{
/**
* Check the version
*/
if (self::$STRAP_TEMPLATE_INFO === null) {
self::$STRAP_TEMPLATE_INFO = confToHash(__DIR__ . '/../../../tpl/strap/template.info.txt');
}
$templateVersion = self::$STRAP_TEMPLATE_INFO['version'];
$comboVersion = PluginUtility::$INFO_PLUGIN['version'];
/** @noinspection DuplicatedCode */
if ($templateVersion !== $comboVersion) {
$strapName = "Strap";
$comboName = "Combo";
$strapLink = "$strapName";
$comboLink = "$comboName";
if ($comboVersion > $templateVersion) {
$upgradeTarget = $strapName;
} else {
$upgradeTarget = $comboName;
}
$upgradeLink = "upgrade $upgradeTarget via the extension manager";
$message = "You should $upgradeLink to the latest version to get a fully functional experience. The version of $comboLink is ($comboVersion) while the version of $strapLink is ($templateVersion).";
LogUtility::msg($message);
throw new ExceptionCompile($message);
}
}
/**
* @throws ExceptionNotFound
*/
public static function getLogoImage(): WikiPath
{
$logosImages = Site::getLogoImagesAsPath();
if (empty($logosImages)) {
throw new ExceptionNotFound("No logo image was installed", "logo");
}
return $logosImages[0];
}
/**
* @return void
* @deprecated
*/
public static function enableSectionEditing()
{
ExecutionContext::getActualOrCreateFromEnv()->getConfig()->setEnableSectionEditing();
}
public static function setDefaultTemplate()
{
global $conf;
$conf['template'] = "dokuwiki";
}
/**
* @return LocalPath[]
*/
public static function getConfigurationFiles(): array
{
$files = [];
foreach (getConfigFiles('main') as $fileConfig) {
$files[] = LocalPath::createFromPathString($fileConfig);
}
return $files;
}
/**
* @return string the base directory for all url
* @throws ExceptionNotFound
*/
public static function getUrlPathBaseDir(): string
{
/**
* Based on {@link getBaseURL()}
*/
global $conf;
if (!empty($conf['basedir'])) {
return $conf['basedir'];
}
$scriptName = LocalPath::createFromPathString($_SERVER['SCRIPT_NAME']);
if ($scriptName->getExtension() === 'php') {
return Url::toUrlSeparator($scriptName->getParent()->toAbsoluteId());
}
$phpSelf = LocalPath::createFromPathString($_SERVER['PHP_SELF']);
if ($phpSelf->getExtension() === "php") {
return Url::toUrlSeparator($scriptName->getParent()->toAbsoluteId());
}
if ($_SERVER['DOCUMENT_ROOT'] && $_SERVER['SCRIPT_FILENAME']) {
$dir = preg_replace('/^' . preg_quote($_SERVER['DOCUMENT_ROOT'], '/') . '/', '',
$_SERVER['SCRIPT_FILENAME']);
return Url::toUrlSeparator(dirname('/' . $dir));
}
throw new ExceptionNotFound("No Base dir");
}
public static function getUrlRewrite(): string
{
global $conf;
$confKey = UrlRewrite::CONF_KEY;
$urlRewrite = $conf[$confKey];
try {
$urlRewriteInt = DataType::toInteger($urlRewrite);
} catch (ExceptionBadArgument $e) {
LogUtility::internalError("The ($confKey) configuration is not an integer ($urlRewrite)");
return UrlRewrite::NO_REWRITE;
}
switch ($urlRewriteInt) {
case UrlRewrite::NO_REWRITE_DOKU_VALUE:
return UrlRewrite::NO_REWRITE;
case UrlRewrite::WEB_SERVER_REWRITE_DOKU_VALUE:
return UrlRewrite::WEB_SERVER_REWRITE;
case UrlRewrite::DOKU_REWRITE_DOKU_VALUE:
return UrlRewrite::VALUE_DOKU_REWRITE;
default:
LogUtility::internalError("The ($confKey) configuration value ($urlRewriteInt) is not a valid value (0, 1 or 2). No rewrite");
return UrlRewrite::NO_REWRITE;
}
}
public static function getDefaultMediaLinking(): string
{
return SiteConfig::getConfValue(MediaMarkup::CONF_DEFAULT_LINKING, MediaMarkup::LINKING_DIRECT_VALUE);
}
public static function shouldEndpointUrlBeAbsolute(): bool
{
global $conf;
return $conf['canonical'] === 1;
}
public static function setEndpointToAbsoluteUrl()
{
global $conf;
$conf['canonical'] = 1;
}
public static function setEndpointToDefaultUrl()
{
global $conf;
$conf['canonical'] = 0;
}
public function getConfig(): SiteConfig
{
if (isset($this->config)) {
return $this->config;
}
$this->config = new SiteConfig($this->executingContext);
return $this->config;
}
}