mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2024-12-14 10:13:05 +02:00
c9632e9874
This parameter `allows the doc code to determine if special handling is needed for the xml document.
566 lines
19 KiB
Perl
566 lines
19 KiB
Perl
####################################################################################################################################
|
|
# DOC MANIFEST MODULE
|
|
####################################################################################################################################
|
|
package BackRestDoc::Common::DocManifest;
|
|
|
|
use strict;
|
|
use warnings FATAL => qw(all);
|
|
use Carp qw(confess);
|
|
|
|
use Cwd qw(abs_path);
|
|
use Exporter qw(import);
|
|
our @EXPORT = qw();
|
|
use File::Basename qw(dirname);
|
|
use Scalar::Util qw(blessed);
|
|
|
|
use lib dirname($0) . '/../lib';
|
|
use pgBackRest::Common::Log;
|
|
use pgBackRest::Common::String;
|
|
use pgBackRest::FileCommon;
|
|
|
|
####################################################################################################################################
|
|
# Operation constants
|
|
####################################################################################################################################
|
|
use constant OP_DOC_MANIFEST => 'DocManifest';
|
|
|
|
use constant OP_DOC_MANIFEST_NEW => OP_DOC_MANIFEST . '->new';
|
|
use constant OP_DOC_MANIFEST_RENDER_GET => OP_DOC_MANIFEST . '->renderGet';
|
|
use constant OP_DOC_MANIFEST_RENDER_LIST => OP_DOC_MANIFEST . '->renderList';
|
|
use constant OP_DOC_MANIFEST_RENDER_OUT_GET => OP_DOC_MANIFEST . '->renderOutGet';
|
|
use constant OP_DOC_MANIFEST_RENDER_OUT_LIST => OP_DOC_MANIFEST . '->renderOutList';
|
|
use constant OP_DOC_MANIFEST_SOURCE_GET => OP_DOC_MANIFEST . '->sourceGet';
|
|
use constant OP_DOC_MANIFEST_VARIABLE_LIST_PARSE => OP_DOC_MANIFEST . '->variableListParse';
|
|
|
|
####################################################################################################################################
|
|
# File constants
|
|
####################################################################################################################################
|
|
use constant FILE_MANIFEST => 'manifest.xml';
|
|
|
|
####################################################################################################################################
|
|
# Render constants
|
|
####################################################################################################################################
|
|
use constant RENDER => 'render';
|
|
use constant RENDER_FILE => 'file';
|
|
|
|
use constant RENDER_TYPE => 'type';
|
|
use constant RENDER_TYPE_HTML => 'html';
|
|
push @EXPORT, qw(RENDER_TYPE_HTML);
|
|
use constant RENDER_TYPE_MARKDOWN => 'markdown';
|
|
push @EXPORT, qw(RENDER_TYPE_MARKDOWN);
|
|
use constant RENDER_TYPE_PDF => 'pdf';
|
|
push @EXPORT, qw(RENDER_TYPE_PDF);
|
|
|
|
####################################################################################################################################
|
|
# CONSTRUCTOR
|
|
####################################################################################################################################
|
|
sub new
|
|
{
|
|
my $class = shift; # Class name
|
|
|
|
# Create the class hash
|
|
my $self = {};
|
|
bless $self, $class;
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
(
|
|
my $strOperation,
|
|
$self->{stryKeyword},
|
|
$self->{stryRequire},
|
|
my $oVariableOverride,
|
|
$self->{strDocPath}
|
|
) =
|
|
logDebugParam
|
|
(
|
|
OP_DOC_MANIFEST_NEW, \@_,
|
|
{name => 'stryKeyword'},
|
|
{name => 'stryRequire'},
|
|
{name => 'oVariableOverride', required => false},
|
|
{name => 'strDocPath', required => false},
|
|
);
|
|
|
|
# Set the base path if it was not passed in
|
|
if (!defined($self->{strDocPath}))
|
|
{
|
|
$self->{strDocPath} = abs_path(dirname($0));
|
|
}
|
|
|
|
# Load the manifest
|
|
$self->{oManifestXml} = new BackRestDoc::Common::Doc("$self->{strDocPath}/manifest.xml");
|
|
|
|
# Iterate the sources
|
|
$self->{oManifest} = {};
|
|
|
|
foreach my $oSource ($self->{oManifestXml}->nodeGet('source-list')->nodeList('source'))
|
|
{
|
|
my $oSourceHash = {};
|
|
my $strKey = $oSource->paramGet('key');
|
|
my $strSourceType = $oSource->paramGet('type', false);
|
|
|
|
logDebugMisc
|
|
(
|
|
$strOperation, 'load source',
|
|
{name => 'strKey', value => $strKey},
|
|
{name => 'strSourceType', value => $strSourceType}
|
|
);
|
|
|
|
$$oSourceHash{doc} = new BackRestDoc::Common::Doc("$self->{strDocPath}/xml/${strKey}.xml");
|
|
|
|
# Read variables from source
|
|
$self->variableListParse($$oSourceHash{doc}->nodeGet('variable-list', false), $oVariableOverride);
|
|
|
|
${$self->{oManifest}}{source}{$strKey} = $oSourceHash;
|
|
${$self->{oManifest}}{source}{$strKey}{strSourceType} = $strSourceType;
|
|
}
|
|
|
|
# Iterate the renderers
|
|
foreach my $oRender ($self->{oManifestXml}->nodeGet('render-list')->nodeList('render'))
|
|
{
|
|
my $oRenderHash = {};
|
|
my $strType = $oRender->paramGet(RENDER_TYPE);
|
|
|
|
# Only one instance of each render type can be defined
|
|
if (defined(${$self->{oManifest}}{&RENDER}{$strType}))
|
|
{
|
|
confess &log(ERROR, "render ${strType} has already been defined");
|
|
}
|
|
|
|
# Get the file param
|
|
$${oRenderHash}{file} = $oRender->paramGet(RENDER_FILE, false);
|
|
|
|
logDebugMisc
|
|
(
|
|
$strOperation, ' load render',
|
|
{name => 'strType', value => $strType},
|
|
{name => 'strFile', value => $${oRenderHash}{file}}
|
|
);
|
|
|
|
# Error if file is set and render type is not pdf
|
|
if (defined($${oRenderHash}{file}) && $strType ne RENDER_TYPE_PDF)
|
|
{
|
|
confess &log(ERROR, 'only the pdf render type can have file set')
|
|
}
|
|
|
|
# Iterate the render sources
|
|
foreach my $oRenderOut ($oRender->nodeList('render-source'))
|
|
{
|
|
my $oRenderOutHash = {};
|
|
my $strKey = $oRenderOut->paramGet('key');
|
|
my $strSource = $oRenderOut->paramGet('source', false, $strKey);
|
|
|
|
$$oRenderOutHash{source} = $strSource;
|
|
|
|
# Get the menu caption
|
|
if (defined($oRenderOut->paramGet('menu', false)) && $strType ne RENDER_TYPE_HTML)
|
|
{
|
|
confess &log(ERROR, "menu is only valid with html render type");
|
|
}
|
|
|
|
# Get the filename
|
|
if (defined($oRenderOut->paramGet('file', false)))
|
|
{
|
|
if ($strType eq RENDER_TYPE_HTML || $strType eq RENDER_TYPE_MARKDOWN)
|
|
{
|
|
$$oRenderOutHash{file} = $oRenderOut->paramGet('file');
|
|
}
|
|
else
|
|
{
|
|
confess &log(ERROR, "file is only valid with html or markdown render types");
|
|
}
|
|
}
|
|
|
|
if (defined($oRenderOut->paramGet('menu', false)))
|
|
{
|
|
if ($strType eq RENDER_TYPE_HTML)
|
|
{
|
|
$$oRenderOutHash{menu} = $oRenderOut->paramGet('menu', false);
|
|
}
|
|
else
|
|
{
|
|
confess &log(ERROR, 'only the html render type can have menu set');
|
|
}
|
|
}
|
|
|
|
logDebugMisc
|
|
(
|
|
$strOperation, ' load render source',
|
|
{name => 'strKey', value => $strKey},
|
|
{name => 'strSource', value => $strSource},
|
|
{name => 'strMenu', value => $${oRenderOutHash}{menu}}
|
|
);
|
|
|
|
$${oRenderHash}{out}{$strKey} = $oRenderOutHash;
|
|
}
|
|
|
|
${$self->{oManifest}}{render}{$strType} = $oRenderHash;
|
|
}
|
|
|
|
# Read variables from manifest
|
|
$self->variableListParse($self->{oManifestXml}->nodeGet('variable-list', false), $oVariableOverride);
|
|
|
|
# use Data::Dumper; confess Dumper($self->{oVariable});
|
|
|
|
# Return from function and log return values if any
|
|
return logDebugReturn
|
|
(
|
|
$strOperation,
|
|
{name => 'self', value => $self}
|
|
);
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# isBackRest
|
|
#
|
|
# Until all the backrest specific code can be abstracted, this function will identify when BackRest docs are being built.
|
|
####################################################################################################################################
|
|
sub isBackRest
|
|
{
|
|
my $self = shift;
|
|
|
|
return($self->variableTest('project-exe', 'pgbackrest'));
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# keywordMatch
|
|
#
|
|
# See if all the keywords were on the command line.
|
|
####################################################################################################################################
|
|
sub keywordMatch
|
|
{
|
|
my $self = shift;
|
|
my $strKeywordRequired = shift;
|
|
|
|
if (defined($strKeywordRequired))
|
|
{
|
|
for my $strKeyword (split(',', $strKeywordRequired))
|
|
{
|
|
$strKeyword = trim($strKeyword);
|
|
|
|
if (!grep(/^$strKeyword$/, @{$self->{stryKeyword}}))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# variableListParse
|
|
#
|
|
# Parse a variable list and store variables.
|
|
####################################################################################################################################
|
|
sub variableListParse
|
|
{
|
|
my $self = shift;
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
my
|
|
(
|
|
$strOperation,
|
|
$oVariableList,
|
|
$oVariableOverride
|
|
) =
|
|
logDebugParam
|
|
(
|
|
OP_DOC_MANIFEST_VARIABLE_LIST_PARSE, \@_,
|
|
{name => '$oVariableList', required => false},
|
|
{name => '$oVariableOverride', required => false}
|
|
);
|
|
|
|
if (defined($oVariableList))
|
|
{
|
|
foreach my $oVariable ($oVariableList->nodeList('variable'))
|
|
{
|
|
if ($self->keywordMatch($oVariable->paramGet('keyword', false)))
|
|
{
|
|
my $strKey = $oVariable->paramGet('key');
|
|
my $strValue = $oVariable->valueGet();
|
|
|
|
if ($oVariable->paramTest('eval', 'y'))
|
|
{
|
|
# In this case we really do want to evaluate the contents of strValue and not treat it as a literal.
|
|
$strValue = eval($strValue); ## no critic (BuiltinFunctions::ProhibitStringyEval)
|
|
|
|
if ($@)
|
|
{
|
|
confess &log(ERROR, "unable to evaluate ${strKey}: $@\n" . $oVariable->valueGet());
|
|
}
|
|
}
|
|
|
|
$self->variableSet($strKey, defined($$oVariableOverride{$strKey}) ? $$oVariableOverride{$strKey} : $strValue);
|
|
|
|
logDebugMisc
|
|
(
|
|
$strOperation, ' load variable',
|
|
{name => 'strKey', value => $strKey},
|
|
{name => 'strValue', value => $strValue}
|
|
);
|
|
}
|
|
}
|
|
}
|
|
|
|
# Return from function and log return values if any
|
|
return logDebugReturn($strOperation);
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# variableReplace
|
|
#
|
|
# Replace variables in the string.
|
|
####################################################################################################################################
|
|
sub variableReplace
|
|
{
|
|
my $self = shift;
|
|
my $strBuffer = shift;
|
|
my $strType = shift;
|
|
|
|
if (!defined($strBuffer))
|
|
{
|
|
return;
|
|
}
|
|
|
|
foreach my $strName (sort(keys(%{$self->{oVariable}})))
|
|
{
|
|
my $strValue = $self->{oVariable}{$strName};
|
|
|
|
$strBuffer =~ s/\{\[$strName\]\}/$strValue/g;
|
|
}
|
|
|
|
if (defined($strType) && $strType eq 'latex')
|
|
{
|
|
$strBuffer =~ s/\\\_/\_/g;
|
|
$strBuffer =~ s/\_/\\\_/g;
|
|
$strBuffer =~ s/\\\#/\#/g;
|
|
$strBuffer =~ s/\#/\\\#/g;
|
|
}
|
|
|
|
return $strBuffer;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# variableSet
|
|
#
|
|
# Set a variable to be replaced later.
|
|
####################################################################################################################################
|
|
sub variableSet
|
|
{
|
|
my $self = shift;
|
|
my $strKey = shift;
|
|
my $strValue = shift;
|
|
my $bForce = shift;
|
|
|
|
if (defined(${$self->{oVariable}}{$strKey}) && (!defined($bForce) || !$bForce))
|
|
{
|
|
confess &log(ERROR, "${strKey} variable is already defined");
|
|
}
|
|
|
|
${$self->{oVariable}}{$strKey} = $self->variableReplace($strValue);
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# variableGet
|
|
#
|
|
# Get the current value of a variable.
|
|
####################################################################################################################################
|
|
sub variableGet
|
|
{
|
|
my $self = shift;
|
|
my $strKey = shift;
|
|
|
|
return ${$self->{oVariable}}{$strKey};
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# variableTest
|
|
#
|
|
# Test that a variable is defined or has an expected value.
|
|
####################################################################################################################################
|
|
sub variableTest
|
|
{
|
|
my $self = shift;
|
|
my $strKey = shift;
|
|
my $strExpectedValue = shift;
|
|
|
|
# Get the variable
|
|
my $strValue = ${$self->{oVariable}}{$strKey};
|
|
|
|
# Return false if it is not defined
|
|
if (!defined($strValue))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
# Return false if it does not equal the expected value
|
|
if (defined($strExpectedValue) && $strValue ne $strExpectedValue)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# sourceGet
|
|
####################################################################################################################################
|
|
sub sourceGet
|
|
{
|
|
my $self = shift;
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
my
|
|
(
|
|
$strOperation,
|
|
$strSource
|
|
) =
|
|
logDebugParam
|
|
(
|
|
OP_DOC_MANIFEST_SOURCE_GET, \@_,
|
|
{name => 'strSource', trace => true}
|
|
);
|
|
|
|
if (!defined(${$self->{oManifest}}{source}{$strSource}))
|
|
{
|
|
confess &log(ERROR, "source ${strSource} does not exist");
|
|
}
|
|
|
|
# Return from function and log return values if any
|
|
return logDebugReturn
|
|
(
|
|
$strOperation,
|
|
{name => 'oSource', value => ${$self->{oManifest}}{source}{$strSource}}
|
|
);
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# renderList
|
|
####################################################################################################################################
|
|
sub renderList
|
|
{
|
|
my $self = shift;
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
my ($strOperation) = logDebugParam(OP_DOC_MANIFEST_RENDER_LIST);
|
|
|
|
# Check that the render output exists
|
|
my @stryRender;
|
|
|
|
if (defined(${$self->{oManifest}}{render}))
|
|
{
|
|
@stryRender = sort(keys(%{${$self->{oManifest}}{render}}));
|
|
}
|
|
|
|
# Return from function and log return values if any
|
|
return logDebugReturn
|
|
(
|
|
$strOperation,
|
|
{name => 'stryRender', value => \@stryRender}
|
|
);
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# renderGet
|
|
####################################################################################################################################
|
|
sub renderGet
|
|
{
|
|
my $self = shift;
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
my
|
|
(
|
|
$strOperation,
|
|
$strType
|
|
) =
|
|
logDebugParam
|
|
(
|
|
OP_DOC_MANIFEST_RENDER_GET, \@_,
|
|
{name => 'strType', trace => true}
|
|
);
|
|
|
|
# Check that the render exists
|
|
if (!defined(${$self->{oManifest}}{render}{$strType}))
|
|
{
|
|
confess &log(ERROR, "render type ${strType} does not exist");
|
|
}
|
|
|
|
# Return from function and log return values if any
|
|
return logDebugReturn
|
|
(
|
|
$strOperation,
|
|
{name => 'oRenderOut', value => ${$self->{oManifest}}{render}{$strType}}
|
|
);
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# renderOutList
|
|
####################################################################################################################################
|
|
sub renderOutList
|
|
{
|
|
my $self = shift;
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
my
|
|
(
|
|
$strOperation,
|
|
$strType
|
|
) =
|
|
logDebugParam
|
|
(
|
|
OP_DOC_MANIFEST_RENDER_OUT_LIST, \@_,
|
|
{name => 'strType'}
|
|
);
|
|
|
|
# Check that the render output exists
|
|
my @stryRenderOut;
|
|
|
|
if (defined(${$self->{oManifest}}{render}{$strType}))
|
|
{
|
|
@stryRenderOut = sort(keys(%{${$self->{oManifest}}{render}{$strType}{out}}));
|
|
}
|
|
|
|
# Return from function and log return values if any
|
|
return logDebugReturn
|
|
(
|
|
$strOperation,
|
|
{name => 'stryRenderOut', value => \@stryRenderOut}
|
|
);
|
|
}
|
|
|
|
####################################################################################################################################
|
|
# renderOutGet
|
|
####################################################################################################################################
|
|
sub renderOutGet
|
|
{
|
|
my $self = shift;
|
|
|
|
# Assign function parameters, defaults, and log debug info
|
|
my
|
|
(
|
|
$strOperation,
|
|
$strType,
|
|
$strKey
|
|
) =
|
|
logDebugParam
|
|
(
|
|
OP_DOC_MANIFEST_RENDER_OUT_GET, \@_,
|
|
{name => 'strType', trace => true},
|
|
{name => 'strKey', trace => true}
|
|
);
|
|
|
|
# use Data::Dumper; print Dumper(${$self->{oManifest}}{render});
|
|
|
|
if (!defined(${$self->{oManifest}}{render}{$strType}{out}{$strKey}))
|
|
{
|
|
confess &log(ERROR, "render out ${strKey} does not exist");
|
|
}
|
|
|
|
# Return from function and log return values if any
|
|
return logDebugReturn
|
|
(
|
|
$strOperation,
|
|
{name => 'oRenderOut', value => ${$self->{oManifest}}{render}{$strType}{out}{$strKey}}
|
|
);
|
|
}
|
|
|
|
1;
|