Apache2-PageKit
view release on metacpan or search on metacpan
lib/Apache2/PageKit/View.pm view on Meta::CPAN
$tmpl->param($key, $value);
}
}
}
# finally, we use the $output_param_object object to fill in template
# get params from $view object
# note that in this case we allow for MODEL_LOOPs as well as MODEL_VARs
my $output_param_object = $view->{output_param_object};
foreach my $key ($output_param_object->param){
my $value = $output_param_object->param($key);
$view->{pkit_pk}->{browser_cache} = 'no';
$tmpl->param($key, $value);
}
my $output = $tmpl->output;
if($record->{has_form}){
# if fillinform_objects is set, then we use that to fill in any HTML
# forms in the template.
my $fif;
if(@{$view->{fillinform_objects}}){
$view->{pkit_pk}->{browser_cache} = 'no';
Encode::_utf8_off($output);
$fif = HTML::FillInForm->new();
$output = $fif->fill(scalarref => \$output,
fobject => $view->{fillinform_objects},
ignore_fields => $view->{ignore_fillinform_fields}
);
Encode::_utf8_on($output);
}
}
if($view->{can_edit} eq 'yes'){
$view->{pkit_pk}->{browser_cache} = 'no';
Apache2::PageKit::Edit::add_edit_links($view, $record, \$output);
}
return \$output;
}
# gets static gzipped file, creating it if necessary
sub get_static_gzip {
my ($view, $filename) = @_;
my ($gzip_mtime, $gzipped_content);
(my $relative_filename = $filename) =~ s!^$view->{view_dir}/!!;
my $gzipped_filename = "$view->{cache_dir}/$relative_filename.gz";
# is the cache entry valid or changed on disc?
if(-f "$gzipped_filename"){
open my $fh, "<$gzipped_filename" or return undef;
binmode $fh;
# read mtime from first line
chomp($gzip_mtime = <$fh>);
# read rest of gzipped content
local $/;
$gzipped_content = <$fh>;
close $fh;
if($view->{reload} ne 'no'){
# is the cache entry valid or changed on disc?
my $mtime = ( stat($filename) )[9];
if($mtime != $gzip_mtime){
$gzipped_content = $view->_create_static_zip($filename, $gzipped_filename);
}
}
} else {
$gzipped_content = $view->_create_static_zip($filename, $gzipped_filename);
}
return $gzipped_content;
}
# opens template, each
sub open_view {
my ($view, $page_id, $pkit_view, $lang) = @_;
return if exists $view->{already_loaded}->{$page_id};
my $record = $view->_fetch_from_file_cache($page_id, $pkit_view, $lang);
unless($record){
# template not cached, load now
$view->_load_page($page_id, $pkit_view);
$record = $view->_fetch_from_file_cache($page_id, $pkit_view, $lang);
die "Error loading record for page_id $page_id and view $pkit_view"
unless $record;
}
if($view->{reload} ne 'no'){
# check for updated files on disk
unless($view->_is_record_uptodate($record, $pkit_view, $page_id)){
# one of the included files changed on disk, reload
$view->_load_page($page_id, $pkit_view);
$record = $view->_fetch_from_file_cache($page_id, $pkit_view, $lang);
}
}
$view->{record} = $record;
$view->{already_loaded}->{$page_id} = 1;
}
sub preparse_templates {
my ($view) = @_;
my $view_dir = $view->{view_dir};
my $load_template_sub = sub {
return unless /\.tmpl$/;
my $template_file = "$File::Find::dir/$_";
my ($pkit_view, $page_id) =
($template_file =~ m!$view_dir/([^/]*)/Page/(.*?)\.(tmpl|tt)$!);
return unless $page_id;
$view->open_view($page_id, $pkit_view);
};
File::Find::find({wanted => $load_template_sub},
# follow => 1},
$view_dir);
}
sub template_file_exists {
my ($view, $page_id, $pkit_view) = @_;
return 1 if $view->_find_template($pkit_view,$page_id);
}
# private methods
# creates gzipped file
sub _create_static_zip {
my ($view, $filename, $gzipped_filename) = @_;
local $/;
open my $fh, "<$filename" or return undef;
binmode $fh;
my $content = <$fh>;
close $fh;
$view->_html_clean(\$content);
my $gzipped_content = Compress::Zlib::memGzip($content);
(my $gzipped_dir = $gzipped_filename) =~ s!(/)?[^/]*?$!!;
File::Path::mkpath("$gzipped_dir");
if ($gzipped_content) {
my $mtime = (stat($filename))[9];
if ( open my $gzip_fh, ">$gzipped_filename" ) {
binmode $gzip_fh;
print $gzip_fh "$mtime\n";
print $gzip_fh $gzipped_content;
close $gzip_fh;
} else {
warn "can not create gzip cache file $view->{cache_dir}/$gzipped_filename: $!";
}
return $gzipped_content;
}
return undef;
}
sub _fetch_from_file_cache {
my ($view, $page_id, $pkit_view, $lang) = @_;
my ($extra_param, $param_hash) = ("", "");
# get a list of requested params in the *.xsl file
if (my @xml_params = sort keys %{$Apache2::PageKit::Content::PAGE_ID_XSL_PARAMS->{$page_id}}) {
my $param_obj = $view->{input_param_object};
for my $xml_param (@xml_params){
my $value = $param_obj->param($xml_param) || '';
$extra_param .= "&$xml_param=" . $value;
}
$param_hash = Digest::MD5::md5_hex($extra_param);
}
my $cache_filename = "$view->{cache_dir}/$page_id.$pkit_view.$lang$param_hash";
if(-f "$cache_filename"){
# cache file exists for specified language
return Storable::lock_retrieve($cache_filename);
} else {
$cache_filename = "$view->{cache_dir}/$page_id.$pkit_view.$view->{default_lang}$param_hash";
if(-f "$cache_filename"){
# cache file exists for default language
return Storable::lock_retrieve($cache_filename);
} else {
return;
}
}
}
sub _find_template {
my ($view, $pkit_view, $id) = @_;
my $template_file = "$view->{view_dir}/$pkit_view/$id.tmpl";
if(-f "$template_file"){
return $template_file;
} else {
$template_file = "$view->{view_dir}/Default/$id.tmpl";
if(-f "$template_file"){
return $template_file;
} else {
return undef;
}
}
}
# clean up html, remove white spaces, etc
lib/Apache2/PageKit/View.pm view on Meta::CPAN
return unless $html_clean_level > 0;
my $h = new HTML::Clean($html_code_ref,$html_clean_level) || die("can not open HTML::Clean object: $!");
$h->strip;
$$html_code_ref = ${$h->data()};
}
sub _include_components {
my ($view, $page_id, $html_code_ref, $pkit_view) = @_;
if ( $view->{relaxed_parser} eq 'yes' ) {
$$html_code_ref =~ s%<(!--)?\s*PKIT_COMPONENT($key_value_pattern+)\s*/?(?(1)--)?>(?:<(!--)?\s*/PKIT_COMPONENT\s*(?(1)--)>)?%get_component($page_id,$2,$view,$pkit_view)%eig;
} else {
$$html_code_ref =~ s%<\s*PKIT_COMPONENT($key_value_pattern+)\s*/?>(<\s*/PKIT_COMPONENT\s*>)?%&get_component($page_id,$1,$view,$pkit_view)%eig;
}
sub get_component {
my ($page_id, $params, $view, $pkit_view) = @_;
my %params = ();
while($params =~ m!$key_value_pattern!ig) {
$params{uc($2)} = $+;
}
my $component_id = delete $params{NAME} or die qq{component item "NAME=..." not found};
unless($component_id =~ s!^/!!){
# relative component, component relative to page_id
(my $page_id_dir = $page_id) =~ s![^/]*$!!;
$component_id = $page_id_dir . $component_id;
while ($component_id =~ s![^/]*/\.\./!!) {};
}
my $cid_key = join '', $component_id, sort %params;
unless ( $view->{component_ids_hash}->{$cid_key}++ ) {
push @{ $view->{component_ids} }, [ $component_id , \%params ];
}
# check for recursive pkit_components
if($view->{component_ids_hash}->{$cid_key} > 100){
die "Likely recursive PKIT_COMPONENTS for component_id $component_id and giving up.";
}
my $template_ref = $view->_load_component($page_id, $component_id, $pkit_view, \%params);
return $$template_ref;
}
}
sub _is_record_uptodate {
my ($view, $record, $pkit_view, $page_id) = @_;
# first check timestamps
my $include_mtimes = $record->{include_mtimes};
while (my ($filename, $cache_mtime) = each %$include_mtimes){
# check if file still exists
unless(-f "$filename"){
return 0;
}
# check if file is up to date
my $file_mtime = (stat($filename))[9];
# print "hi $filename - $cache_mtime - $file_mtime<br>";
if($file_mtime != $cache_mtime){
return 0;
}
if($filename =~ m!^$view->{view_dir}/Default/! && $pkit_view ne 'Default'){
# check to see if any new files have been uploaded to the $pkit_view dir
(my $check_filename = $filename) =~ s!^$view->{view_dir}/Default/!$view->{view_dir}/$pkit_view/!;
if (-f "$check_filename"){
return 0;
}
}
}
# record up to date!
return 1;
}
# here the usage of "component" also includes page
sub _load_component {
my ($view, $page_id, $component_id, $pkit_view, $component_params) = @_;
my $template_file = $view->_find_template($pkit_view, $component_id);
my $template_ref;
unless($template_file){
# no template file exists, attempt to generate from XML and XSL files
# currently only XML::LibXSLT is supported
$template_ref = $view->{content}->generate_template($page_id, $component_id, $pkit_view, $view->{input_param_object}, $component_params);
} else {
open my $template_fh, "<$template_file" or die "can not read $template_file";
my $default_input_charset = $view->{default_input_charset};
binmode $template_fh, ":encoding($default_input_charset)";
local $/;
my $template = <$template_fh>;
close $template_fh;
# expand PKIT_MACRO tags
$template =~ s!<\s*PKIT_MACRO$key_value_pattern\s*/?>!$component_params->{uc($+)} || ''!egi;
$template_ref = \$template;
my $mtime = (stat(_))[9];
$view->{include_mtimes}->{$template_file} = $mtime;
}
if($view->{can_edit} eq 'yes'){
Apache2::PageKit::Edit::add_component_edit_stubs($view, $page_id, $template_ref, $pkit_view);
}
$view->_include_components($page_id,$template_ref,$pkit_view);
return $template_ref;
}
sub _load_page {
my ($view, $page_id, $pkit_view) = @_;
$Apache2::PageKit::Content::PAGE_ID_XSL_PARAMS->{$page_id} = {};
my $content = $view->{content} ||= Apache2::PageKit::Content->new(
content_dir => $view->{content_dir},
view_dir => $view->{view_dir},
default_lang => $view->{default_lang},
relaxed_parser => $view->{relaxed_parser},
template_class => $view->{template_class},
);
$view->{lang_tmpl} = $content->{lang_tmpl} = {};
$content->{include_mtimes} = {};
$view->{component_ids_hash} = {};
# we add Config.xml to the hash of files to be checked for mtimes,
# in case default_input_charset or default_output_charset changes!
(my $config_file = $view->{view_dir}) =~ s!/View$!/Config/Config.xml!;
my $config_mtime = ( stat($config_file) )[9];
$view->{include_mtimes} = {$config_file => $config_mtime};
my $template_file = $view->_find_template($pkit_view, $page_id);
my $template_ref = $view->_load_component($page_id,$page_id,$pkit_view);
# remove PKIT_COMMENT parts.
my $pkit_comment_re = $re_helper{ $view->{relaxed_parser} eq 'yes' ? 'relaxed_parser' : 'std_parser' }->{pkit_comment_re};
$$template_ref =~ s/$pkit_comment_re//sgi;
# my $template_file = $view->_find_template($pkit_view, $page_id);
my $lang_tmpl = $content->process_template($page_id, $template_ref);
# add used content file(s) to the mtimes hash
while( my ( $file, $mtime ) = each( %{ $content->{include_mtimes} } ) ) {
$view->{include_mtimes}->{$file} = $mtime;
}
# go through content files (which have had content filled in)
while (my ($lang, $filtered_html) = each %$lang_tmpl){
my $exclude_params_set = $view->_preparse_model_tags($filtered_html);
$view->_html_clean($filtered_html);
my $has_form = ($$filtered_html =~ m!<form!i);
my $tmpl;
eval {
$tmpl = $view->{template_class}->new(scalarref => $filtered_html,
# don't die when we set a parameter that is not in the template
die_on_bad_params=>0,
# built in __FIRST__, __LAST__, etc vars
loop_context_vars=>1,
max_includes => 50,
global_vars=>1);
};
if($@){
die "Can not load template (MODEL TAGS) for $page_id: $@"
}
my $record = {
exclude_params_set => $exclude_params_set,
filename => $template_file,
html_template => $tmpl,
include_mtimes => $view->{include_mtimes},
component_ids => $view->{component_ids},
has_form => $has_form,
};
# make directories, if approriate
(my $dir = $page_id) =~ s!(/)?[^/]*?$!!;
if($dir){
File::Path::mkpath("$view->{cache_dir}/$dir");
}
my ($extra_param, $param_hash) = ("", "");
# get a list of requested params in the *.xsl file
if (my @xml_params = sort keys %{$Apache2::PageKit::Content::PAGE_ID_XSL_PARAMS->{$page_id}}) {
my $param_obj = $view->{input_param_object};
for my $xml_param (@xml_params){
my $value = $param_obj->param($xml_param) || '';
lib/Apache2/PageKit/View.pm view on Meta::CPAN
# get params from $view object
# note that in this case we allow for MODEL_LOOPs as well as MODEL_VARs
my $output_param_object = $view->{output_param_object};
foreach my $key ( $output_param_object->param ) {
my $value = $output_param_object->param($key);
$view->{pkit_pk}->{browser_cache} = 'no';
$tt_params{$key} = $value;
}
my $output = Template::Context->new->process(Template::Document->new( $record->{filtered_html} ), \%tt_params );
if ( $record->{has_form} ) {
# if fillinform_objects is set, then we use that to fill in any HTML
# forms in the template.
my $fif;
if ( @{ $view->{fillinform_objects} } ) {
$view->{pkit_pk}->{browser_cache} = 'no';
Encode::_utf8_off($output);
$fif = HTML::FillInForm->new();
$output = $fif->fill(
scalarref => \$output,
fobject => $view->{fillinform_objects},
ignore_fields => $view->{ignore_fillinform_fields}
);
Encode::_utf8_on($output);
}
}
if ( $view->{can_edit} eq 'yes' ) {
$view->{pkit_pk}->{browser_cache} = 'no';
Apache2::PageKit::Edit::add_edit_links( $view, $record, \$output );
}
return \$output;
}
######################################################
sub _load_page {
my ( $view, $page_id, $pkit_view ) = @_;
# solange HTML::Template::XPath noch nichts mit Tempate Toolkit anfangen kann,
# HTML::Template verwenden.
my $content_template_class = $view->{template_class};
$content_template_class = 'HTML::Template' if $content_template_class eq 'Template';
my $content = $view->{content} ||= Apache2::PageKit::Content->new(
content_dir => $view->{content_dir},
view_dir => $view->{view_dir},
default_lang => $view->{default_lang},
relaxed_parser => $view->{relaxed_parser},
template_class => $content_template_class,
);
$view->{lang_tmpl} = $content->{lang_tmpl} = {};
$content->{include_mtimes} = {};
$view->{component_ids_hash} = {};
# we add Config.xml to the hash of files to be checked for mtimes,
# in case default_input_charset or default_output_charset changes!
( my $config_file = $view->{view_dir} ) =~ s!/View$!/Config/Config.xml!;
my $config_mtime = ( stat($config_file) )[9];
$view->{include_mtimes} = { $config_file => $config_mtime };
my $template_file = $view->_find_template( $pkit_view, $page_id );
my $template_ref = $view->_load_component( $page_id, $page_id, $pkit_view );
# remove PKIT_COMMENT parts.
my $pkit_comment_re = $re_helper{ $view->{relaxed_parser} eq 'yes' ? 'relaxed_parser' : 'std_parser' }->{pkit_comment_re};
$$template_ref =~ s/$pkit_comment_re//sgi;
# my $template_file = $view->_find_template($pkit_view, $page_id);
my $lang_tmpl = $content->process_template( $page_id, $template_ref );
# add used content file(s) to the mtimes hash
while ( my ( $file, $mtime ) = each( %{ $content->{include_mtimes} } ) ) {
$view->{include_mtimes}->{$file} = $mtime;
}
# go through content files (which have had content filled in)
while ( my ( $lang, $filtered_html ) = each %$lang_tmpl ) {
my $exclude_params_set = $view->_preparse_model_tags($filtered_html);
$view->_html_clean($filtered_html);
my $has_form = ( $$filtered_html =~ m!<form!i );
my $tt_parser = Template::Parser->new;
my $record = {
exclude_params_set => $exclude_params_set,
filename => $template_file,
include_mtimes => $view->{include_mtimes},
component_ids => $view->{component_ids},
has_form => $has_form,
filtered_html => $tt_parser->parse($$filtered_html) || die $tt_parser->error(),
};
# make directories, if approriate
( my $dir = $page_id ) =~ s!(/)?[^/]*?$!!;
if ($dir) {
File::Path::mkpath("$view->{cache_dir}/$dir");
}
my ( $extra_param, $param_hash ) = ( "", "" );
# get a list of requested params in the *.xsl file
if ( my @xml_params = sort keys %{ $Apache2::PageKit::Content::PAGE_ID_XSL_PARAMS->{$page_id} } ) {
my $param_obj = $view->{input_param_object};
for my $xml_param (@xml_params) {
my $value = $param_obj->param($xml_param) || '';
$extra_param .= "&$xml_param=" . $value;
}
$param_hash = Digest::MD5::md5_hex($extra_param);
}
# Store record
Storable::lock_store( $record, "$view->{cache_dir}/$page_id.$pkit_view.$lang$param_hash" );
}
# include mtimes and component_ids are filled in by _include_components
# and _fill_in_content
( run in 1.234 second using v1.01-cache-2.11-cpan-39bf76dae61 )