# Copyright 2002-2008 Josh Clark and Global Moxie, LLC. This code cannot be
# redistributed without permission from globalmoxie.com.  For more
# information, consult your Big Medium license.
#
# $Id: Page.pm 3285 2008-08-26 12:19:55Z josh $

package BigMed::Content::Page;
use strict;
use warnings;
use utf8;
use Carp;

use base qw(BigMed::Content);
use BigMed::PageVersion;
use BigMed::Filter;

###########################################################
# SETUP PAGE DATA SCHEMA AND RELATIONSHIPS
###########################################################

my @data_schema = (
    {   name    => 'slug',
        type    => 'url_safe',
        index   => 1,
        unique  => 1,
        default => q{},
    },
    {   name    => 'description',
        type    => 'rich_text_brief',
        default => q{},
    },
    {   name    => 'meta_description',
        type    => 'simple_text',
        default => q{},
    },
    {   name    => 'meta_keywords',
        type    => 'simple_text',
        default => q{},
    },
    {   name    => 'flags',
        type    => 'key_boolean',
        default => {},
    },
);
my %has_objects = (
    pullquote => {
        class     => 'BigMed::Pullquote',
        id_column => 'page',
        sort      => sub { BigMed::Pullquote->sort_embedded(@_) },
        embed     => 1,
    },
    comment      => { class => 'BigMed::Comment', id_column => 'page' },
    related_link => {
        class         => 'BigMed::URL',
        id_column     => 'linkid',
        source_column => 'linktype',
        sortable      => 1,
        sort          => \&_link_sort,
    },
);

my %points_to_objects = (
    'media' => {  #should be same as content, but with the link_position field
        class => sub {
            require BigMed::Media;
            BigMed::Media->media_classes();
        },
        limit_num  => undef,
        limit_type => undef,
        points     => 1,
        preview    => { html => \&BigMed::Content::_media_preview },
        sort       => \&BigMed::Content::_media_sort,
        embed      => 1,
        metadata   => [
            {   id        => 'link_position',
                prompt_as => 'value_list',
                options   => ['none', 'all', 'spot', 'links'],
                labels    => {
                    'none'  => 'CONTENT_MEDIA_LINK_none',
                    'all'   => 'CONTENT_MEDIA_LINK_all',
                    'spot'  => 'CONTENT_MEDIA_LINK_spot',
                    'links' => 'CONTENT_MEDIA_LINK_links',
                },
                default     => 'none',
                label       => 'CONTENT_MEDIA_Link_position',
                description => 'CONTENT_MEDIA_DESC_Link_position',
                depend      => 'can_link',
            },
            {   id        => 'position',
                prompt_as => 'body_position',
                label     => 'CONTENT_MEDIA_Page Position',
                default   => 'block:1',
            },
            {   id        => 'align',
                prompt_as => 'alignment',
                label     => 'CONTENT_MEDIA_Alignment',
                options   => ['default', 'left', 'center', 'right'],
                default   => 'default',
            },
            {   id          => 'priority',
                prompt_as   => 'priority_slider',
                default     => '500',
                parse_as    => 'number_integer_positive',
                label       => 'CONTENT_MEDIA_Priority',
                description => 'CONTENT_MEDIA_DESC_Priority',
            },
            {   id        => 'caption',
                prompt_as => 'rich_text_brief',
                label     => 'CONTENT_MEDIA_Caption',
            },
            {   id        => 'hotlink_url',
                prompt_as => 'url',
                label     => 'CONTENT_MEDIA_Hotlink_URL',
                default   => 'http://',
                depend    => 'can_hotlink',
            },
        ],
    },
    author => {
        class    => 'BigMed::Person',
        preview  => { html => \&_author_preview },
        metadata => [
            {   id          => 'blurb',
                label       => 'PAGE_Author blurb',
                description => 'PAGE_DESC_Author blurb',
                prompt_as   => 'rich_text_brief',
                parse_as    => 'rich_text_brief',
            },
            {   id        => 'priority',
                prompt_as => 'hidden',
            },
        ],
        sortable => 1,
        sort     => \&_author_sort,
    },
    tag => {
        class         => 'BigMed::Tag',
        custom_prompt => 'tags',
        custom_save   => \&save_tags,
        sort          => \&_tag_sort,
    },
);


###########################################################
# SET UP EDIT FIELDS
###########################################################

#some common edit field combos
my $TITLE_CONTENT = {
    title  => 'PAGE_FS_Content',
    id     => 'bmfsPageContent',
    fields => [
        {   column      => 'title',
            description => 'BM_rich_text_inline_notice',
            required    => 1,
        },
        { custom_obj => 1, },
        {   column      => 'content',
            description => 'PAGE_DESC_Text',
        },
    ],
};
my $ABOUT_PAGE = {
    title  => 'PAGE_FS_About the Page',
    id     => 'bmfsAboutPage',
    fields => [
        {   column      => 'description',
            description => 'PAGE_DESC_Description',

        },
        {   column      => 'sections',
            description => 'PAGE_DESC_Section',
            required    => 1,
            multiple    => 10,
            prompt_as   => 'select_section',
        },
        { relation => 'tag', },
    ],
};
my $AUTHORS = {
    title  => 'PAGE_FS_Authors',
    id     => 'bmfsAuthors',
    fields => [{ relation => 'author', },],
};

my $MEDIA = {
    title  => 'CONTENT_FS_Media',
    id     => 'bmfsMedia',
    fields => [{ relation => 'media' }],
};
my $PULLQUOTES = {
    title  => 'PAGE_FS_Pullquotes',
    id     => 'bmfsPullquotes',
    fields => [{ relation => 'pullquote' }],
};
my $RELATED = {
    title  => 'PAGE_FS_Related',
    id     => 'bmfsRelated',
    fields => [{ relation => 'related_link' }],
};
my $PAGE_PREFS = {
    title  => 'PAGE_FS_Page Preferences',
    id     => 'bmfsPagePrefs',
    fields => [
        {   column      => 'slug',
            description => 'PAGE_DESC_Slug',
        },
        {   column          => 'flags',
            prompt_callback => sub {
                my $app = shift;
                require BigMed::Plugin;
                BigMed::Plugin->load_formats;
                my @options = BigMed::Format->page_flags;
                my %labels  =
                  map { $_ => $app->language("PAGEFLAG_$_") } @options;
                return ( options => \@options, labels => \%labels );
              }
        },
    ],
    optional => 1,
};
my $SEARCH_ENGINES = {
    title  => 'PAGE_FS_For Search Engines',
    id     => 'bmfsSearchEngine',
    fields =>
      [{ column => 'meta_description', }, { column => 'meta_keywords', },],
    optional => 1,
};
my $PUBLISH_INFO = {
    title  => 'CONTENT_FS_Publish Info',
    id     => 'bmfsPublishInfo',
    fields => [
        {   column          => 'pub_status',
            required        => 1,
            prompt_callback => \&BigMed::Content::pub_status_params,
        },
        {   column      => 'priority',
            prompt_as   => 'priority_slider',
            description => 'CONTENT_DESC_Priority',
        },
        {   column          => 'owner',
            required        => 1,
            prompt_as       => 'value_list',
            prompt_callback => \&BigMed::Content::owner_prompt_params,
        },
        {   column          => 'auto_pub_time',
#use default start year: 20 years back from current year
#                start_year      => ( localtime(time) )[5] + 1900,
            option_label    => 'CONTENT_Schedule publication time',
            prompt_callback => sub {
                BigMed::Content::auto_time_prompt_params( @_,
                    'auto_pub_time' );
            },
            parse_callback => \&BigMed::Content::auto_time_parse_params,
        },

        {   column          => 'auto_unpub_time',
            start_year      => ( localtime(time) )[5] + 1900,
            option_label    => 'CONTENT_Schedule unpublication time',
            prompt_callback => sub {
                BigMed::Content::auto_time_prompt_params( @_,
                    'auto_unpub_time' );
            },
            parse_callback => \&BigMed::Content::auto_time_parse_params,
        },
    ],
};

###########################################################
# REGISTER PAGE SUBTYPES
###########################################################

my $PAGE = 'BigMed::Content::Page';

my $default_edit_fields = [
    $TITLE_CONTENT, $ABOUT_PAGE,     $AUTHORS,
    $MEDIA,         $PULLQUOTES,     $RELATED,
    $PAGE_PREFS,    $SEARCH_ENGINES, $PUBLISH_INFO,
];

#register as a content class
$PAGE->register_content_class(
    source        => 'pages',
    label         => 'page',
    elements      => \@data_schema,
    has           => \%has_objects,
    points_to     => \%points_to_objects,
    editor_fields => $default_edit_fields,
);

###########################################################
# PAGE METHODS
###########################################################

my %PageUrl;
my %PageUrlRelation;

sub register_content_subtype {    #overrides content.pm's subtype
    my $parent_class = shift;
    $parent_class->SUPER::register_content_subtype(@_);
    my %param = @_;
    $PageUrl{ $param{name} } = $param{url_hook}
      if ref $param{url_hook} eq 'CODE';
    $PageUrlRelation{ $param{name} } = $param{url_relation}
      if $param{url_relation};
    return 1;
}

sub url_relationships {
    my $obj_or_class = shift;
    my $class = ref $obj_or_class || $obj_or_class;
    my %relation = map { $_ => 1 } ( values %PageUrlRelation );
    return keys %relation;
}

sub page_url {
    my ( $page, $site, $rparam ) = @_;
    croak 'page_url method requires site object' if !ref $site;
    if ( $page->subtype && $PageUrl{ $page->subtype } ) {
        my $url =
          $PageUrl{ $page->subtype }->( $page, $site, $rparam );
        return $url if $url;
    }

    #look up the section
    $rparam ||= {};
    my $sec_id = $page->effective_section( $site, $rparam->{section} );
    return $sec_id ? $page->_url_in_section( $site, $sec_id ) : $sec_id;
}

sub active_page_url {
    my ( $page, $site, $rparam ) = @_;
    croak 'active_page_url requires site object' if !ref $site;

    if ( $page->subtype && $PageUrl{ $page->subtype } ) {
        my $url =
          $PageUrl{ $page->subtype }->( $page, $site, $rparam );
        return $url if $url;
    }

    #page is active if published and belongs to active section
    return q{} if $page->pub_status && $page->pub_status ne 'published';
    
    #check cache before assembling url
    my $context_sec = $rparam->{section} ? $rparam->{section}->id : '_HOME';
    my $url = $page->stash("PAGE:active_url_for_$context_sec");
    return $url if $url;
    
    my $rkids = $rparam ? $rparam->{rkids} : undef;
    my $sec_id =
      $page->effective_active_section( $site, $rparam->{section}, $rkids )
      or return q{}; #no active url
    $url = $page->_url_in_section( $site, $sec_id ) or return;
    $page->set_stash("PAGE:active_url_for_$context_sec", $url);
    return $url;
}

sub _url_in_section {
    my ( $page, $site, $sec_id ) = @_;
    
    my $url     = $site->directory_url($sec_id)     or return;
    my $section = $site->section_obj_by_id($sec_id) or return;
    my $slug = ( $section->page == $page->id ) ? 'index' : $page->slug;
    return $page->set_error(
        head => 'PAGE_Page has no slug name',
        text => 'PAGE_TEXT_Page has no slug name'
      )
      if !$slug;

    require BigMed::Format::HTML;
    my $suffix = BigMed::Format::HTML->suffix();
    return "$url/$slug.$suffix";
}

###########################################################
# REGISTER SUBTYPES
###########################################################

#article subtype -- same as base class
$PAGE->register_content_subtype( name => 'article', default => 1 );

#section subtype
$PAGE->register_content_subtype(    #modified editor fields
    name          => 'section',
    url_hook      => \&_section_page_url,
    editor_fields => [
        $TITLE_CONTENT,
        {   title  => 'PAGE_FS_About the Page',
            id     => 'bmfsAboutPage',
            fields => [
                {   column      => 'description',
                    description => 'PAGE_DESC_Description',
                },
                {   column    => 'sections',
                    required  => 1,
                    prompt_as => 'hidden',
                },
                { relation => 'tag', },
            ],
        },
        $AUTHORS, $MEDIA,
        $PULLQUOTES,
        $SEARCH_ENGINES,
    ],
);

my $DOWNLOAD_METADATA = [
    {   id      => 'link_to',
        label   => 'DOWNLOAD_Link Destination',
        options => ['page', 'document'],
        labels  => {
            document => 'DOWNLOAD_Link to document',
            page     => 'DOWNLOAD_Link to page',
        },
        default   => 'page',
        prompt_as => 'value_list',
        parse_as  => 'value_list',
    },
];

#download subtype
$PAGE->register_content_subtype(    #modified editor fields
    name         => 'download',
    url_hook     => \&_download_url,
    url_relation => 'download',
    content_hook => \&_download_content,
    points_to    => {
        download => {
            class     => 'BigMed::Media::Document',
            preview   => { html => \&_download_preview },
            metadata  => $DOWNLOAD_METADATA,
            limit_num => 1,
            required  => 1,
        },
    },
    editor_fields => [
        {   title  => 'DOWNLOAD_FS_Download document',
            id     => 'bmfsdownload',
            fields => [
                {   column      => 'title',
                    required    => 1,
                    label       => 'DOWNLOAD_Title',
                    description => 'BM_rich_text_inline_notice',
                },
                { relation => 'download' }
            ],
        },
        {   title  => 'PAGE_FS_About the download',
            id     => 'bmfsAboutPage',
            fields => [
                {   column      => 'description',
                    description => 'PAGE_DESC_Description',

                },
                {   column      => 'sections',
                    description => 'PAGE_DESC_Section',
                    required    => 1,
                    multiple    => 7,
                    prompt_as   => 'select_section',
                },
                { relation => 'tag', },
            ],
        },
        {   title  => 'DOWNLOAD_FS_Content',
            id     => 'bmfsPageContent',
            fields => [
                {   column      => 'content',
                    description => 'PAGE_DESC_Text',
                },
            ],
        },
        $AUTHORS,
        $MEDIA,
        $PULLQUOTES,
        $RELATED,
        $PAGE_PREFS,
        $SEARCH_ENGINES,
        $PUBLISH_INFO,
    ],
);

#podcast subtype
$PAGE->register_content_subtype(    #modified editor fields
    name         => 'podcast',
    url_hook     => \&_podcast_url,
    url_relation => 'podcast',
    content_hook => \&_podcast_content,
    points_to    => {
        podcast => {
            class    => 'BigMed::Media::AV',
            preview  => { html => \&_download_preview },
            metadata => [
                {   id      => 'link_to',
                    label   => 'DOWNLOAD_Link Destination',
                    options => ['page', 'document'],
                    labels  => {
                        document => 'DOWNLOAD_Link to document',
                        page     => 'DOWNLOAD_Link to page',
                    },
                    default   => 'page',
                    prompt_as => 'value_list',
                    parse_as  => 'value_list',
                }
            ],
            limit_num => 1,
            required  => 1,
        },
    },
    editor_fields => [
        {   title  => 'PODCAST_FS_Podcast',
            id     => 'bmfspodcast',
            fields => [
                {   column      => 'title',
                    required    => 1,
                    label       => 'DOWNLOAD_Title',
                    description => 'BM_rich_text_inline_notice',
                },
                { relation => 'podcast' }
            ],
        },
        {   title  => 'PAGE_FS_About the podcast',
            id     => 'bmfsAboutPage',
            fields => [
                {   column      => 'description',
                    description => 'PAGE_DESC_Description',

                },
                {   column      => 'sections',
                    description => 'PAGE_DESC_Section',
                    required    => 1,
                    multiple    => 7,
                    prompt_as   => 'select_section',
                },
                { relation => 'tag', },
            ],
        },
        {   title  => 'PODCAST_FS_Content',
            id     => 'bmfsPageContent',
            fields => [
                {   column      => 'content',
                    description => 'PAGE_DESC_Text',
                },
            ],
        },
        $AUTHORS,
        $MEDIA,
        $PULLQUOTES,
        $RELATED,
        $PAGE_PREFS,
        $SEARCH_ENGINES,
        $PUBLISH_INFO,
    ],
);

#link subtype
$PAGE->register_content_subtype(    #modified editor fields
    name         => 'link',
    url_hook     => \&_link_url,
    url_relation => 'link_url',
    content_hook => \&_link_content,
    has          => {
        link_url => {
            class         => 'BigMed::ExtURL',
            id_column     => 'linkid',
            source_column => 'linktype',
            limit_num     => 1,
            required      => 1,
        },
    },
    editor_fields => [
        {   title  => 'LINK_FS_Link',
            id     => 'bmfslinkinfo',
            fields => [
                {   column      => 'title',
                    required    => 1,
                    label       => 'DOWNLOAD_Title',
                    description => 'BM_rich_text_inline_notice',
                },
                { relation => 'link_url' }
            ],
        },
        {   title  => 'PAGE_FS_About the link',
            id     => 'bmfsAboutPage',
            fields => [
                {   column      => 'description',
                    description => 'PAGE_DESC_Description',

                },
                {   column      => 'sections',
                    description => 'PAGE_DESC_Section',
                    required    => 1,
                    multiple    => 7,
                    prompt_as   => 'select_section',
                },
                { relation => 'tag', },
            ],
        },
        {   title  => 'LINK_FS_Content',
            id     => 'bmfsPageContent',
            fields => [
                {   column      => 'content',
                    description => 'PAGE_DESC_Text',
                },
            ],
        },
        $AUTHORS,
        $MEDIA,
        $PULLQUOTES,
        $RELATED,
        $PAGE_PREFS,
        $SEARCH_ENGINES,
        $PUBLISH_INFO,
    ],
);

###########################################################
# RELATIONSHIP HELPERS: AUTHOR
###########################################################

sub authors { #@_ = [0]page, [1]rcache, optional pointer selection
    my @pairs = $_[0]->sorted_related_objects('author', $_[1]);
    my @names = ( map { $_->[1]->name } @pairs ) or return q{};
    return @names == 1
      ? $names[0]
      : join( ', ', @names[0 .. @names - 2] ) . " &amp; $names[-1]";
}

sub _author_preview {
    my ( $app, $item, $robj_preview ) = @_;
    my %meta = $item->[0]->metadata();

    #add caption to existing html if indicated
    my $obj_html = $robj_preview->{PREVIEW_HTML} || q{};
    require BigMed::Filter;
    my $caption = BigMed::Filter->filter( $meta{blurb} );
    $caption = $item->[1]->sanitize_preview_html($app, $caption);
    $obj_html =~ s/(<div class="bmcpMediaCaption">)/$1$caption/ms;
    return ( PREVIEW_HTML => $obj_html, );
}

sub _author_sort {
    return map { $_->[0] }
      sort     {             # descending priority order, then last name
        $b->[1] <=> $a->[1] || $a->[2] cmp $b->[2]
      } map {
        my %meta = $_->[0]->metadata;
        [$_, ( $meta{priority} || 0 ), ( $_->[1]->last_name || q{} )];
      } @_;
}

###########################################################
# RELATIONSHIP HELPERS: RELATED LINKS
###########################################################

sub related_links {
    my ( $page, $site, $rcache ) = @_; #rcache is optional pointer selection
    my @links;
    foreach my $link ( $page->sorted_related_objects('related_link', $rcache) ) {
        my ( $title, $url ) = $link->title_and_url($site);
        push @links,
          { title => $title, url => $url, new_win => $link->new_win }
          if $title;
    }
    return @links;
}

sub _link_sort {    #descending priority
    return map { $_->[0] }
      sort     { $b->[1] <=> $a->[1] }
      map { [$_, ( $_->priority || 0 )] } @_;
}

###########################################################
# RELATIONSHIP HELPERS: TAGS
###########################################################

sub save_tags {
    my ($app, $page) = @_;
    my %field = $app->parse_submission(
        { parse_as => 'tags',
        id       => 'BM_MINI_tag', }
    );
    return $app->set_error(
        head => 'BM_Trouble_processing_form',
        text => $field{_ERROR}
    ) if $field{_ERROR};
    return BigMed::Tag->set_page_tags($page, $field{'BM_MINI_tag'});
}

sub _tag_sort { #alphabetical
    return map { $_->[0] }
      sort     { $a->[1] cmp $b->[1] }
      map { [$_, lc $_->[1]->name] } @_;
}

###########################################################
# SUBTYPE HELPERS: DOWNLOADS/ PODCASTS
###########################################################

sub _download_preview {
    my ( $app, $item, $robj_preview ) = @_;
    my %meta = $item->[0]->metadata();
    my $link_to = $meta{link_to} || 'page';
    return (
        STATUS_HTML => $app->language( 'DOWNLOAD_Link to ' . $link_to ) );
}

sub _file_url {
    my ( $page, $site, $rparam, $relation ) = @_;

    my $pair = ( $page->load_related_objects($relation, $rparam->{rcache}) )[0]
      or return q{};
    my %meta = $pair->[0]->metadata;
    my $link_to = $meta{link_to} || 'page';
    return q{} if $link_to eq 'page';
    my $file = $pair->[1]->filename or return q{};
    return $site->doc_url . "/$file";
}
sub _download_url { return _file_url( @_, 'download' ) }
sub _podcast_url  { return _file_url( @_, 'podcast' ) }

sub _file_content {
    my ( $self, $context, $content, $relation ) = @_;
    my $pair =
      ( $self->load_related_objects($relation, $context->relation_cache) )[0]
      or return $content;
    my $doc      = $pair->[1];
    my $file     = $doc->filename or return $content;
    my $site     = $context->site;
    my $filesize = $doc->filesize($site);
    $filesize =~ s/ /&#160;/ms;
    my $suffix = ( $file =~ /.*[.](\S+)\z/ms )[0] || q{};
    my $url    = $site->doc_url . "/$file";
    my $title  = $doc->title;
    return <<"DOWNLOAD_CONTENT";
        <div class="bmc_$relation">
            <a href="$url" class="bm_docicon bm_${suffix}DocIcon">$title</a>
            ($filesize)
        </div>
        $content
DOWNLOAD_CONTENT
}
sub _download_content { return _file_content( @_, 'download' ) }
sub _podcast_content  { return _file_content( @_, 'podcast' ) }

###########################################################
# SUBTYPE HELPERS: LINK
###########################################################

sub _link_url {
    my ( $page, $site, $rparam ) = @_;
    
    my $exturl = ( $page->load_related_objects('link_url', $rparam->{rcache}) )[0] or return q{};
    return $exturl->link_to eq 'url' ? $exturl->url : q{};
}

my $NEW_WIN = ' target="newsite"';

sub _link_content {
    my ( $self, $context, $content ) = @_;
    my $exturl =
      ( $self->load_related_objects('link_url', $context->relation_cache) )[0]
      or return $content;
    my ( $text, $url, $new_win ) =
      ( $exturl->text, $exturl->url, $exturl->new_win );
    my $onclick = q{};
    if ( $new_win eq 'yes' ) {
        $onclick = $NEW_WIN;
    }
    elsif ($new_win eq 'default'
        && $context->site->get_pref_value('html_links_window') )
    {
        my @domains =
          $context->site->get_pref_value('html_links_window_intdomains');
        my $found;
        foreach my $dom (@domains) {
            $found = 1, last if index( $url, $dom ) == 0;
        }
        $onclick = $NEW_WIN if !$found;
    }
    return <<"LINK_CONTENT";
        <div class="bmc_external_link">
            <a href="$url"$onclick>$text</a>
        </div>
        $content
LINK_CONTENT

}

###########################################################
# SUBTYPE HELPERS: SECTION PAGE
###########################################################

sub _section_page_url {
    my ( $page, $site, $rparam ) = @_;
    my $sec_id = $page->effective_active_section( $site, $rparam->{section} )
      or return q{};
    my $sec = $site->section_obj_by_id($sec_id) or return q{};
    return $sec->alias || q{};
}

###########################################################
# VERSIONING
###########################################################

sub save_version {
    my $page = shift;
    my $pv = BigMed::PageVersion->new;
    $pv->set_site( $page->site );
    $pv->set_page( $page->id );
    $pv->set_version($page->version);
    $pv->set_content($page->content);
    $pv->set_editor( $page->last_editor );
    return $pv->save;
}

__PACKAGE__->add_callback( 'before_save', \&_before_page_save );
__PACKAGE__->add_callback( 'after_save',  \&_after_page_save );

sub _before_page_save {
    my $page = shift;
    return 1 if !$page->is_modified;

    #get last saved version and set version info
    $page->update_id or return;
    my $orig = $page->fetch( { site => $page->site, id => $page->id } );
    my $version = ($orig && $orig->version) ? $orig->version + 1 : 1;
    $page->set_version($version);

    #stow version if first save or changing content from previous
    my $ntext = $page->content || 'RichText:';
    my $otext;
    if (   !$orig
        || !( $otext = $orig->content )
        || BigMed::Filter->filter($otext) ne BigMed::Filter->filter($ntext) )
    {
        $page->set_stash( '_PAGE_BEFORESAVE_newversion', 1 );
    }
    return 1;
}

sub _after_page_save {
    my $page = shift;
    return 1 if !$page->stash('_PAGE_BEFORESAVE_newversion');
    $page->set_stash( '_PAGE_BEFORESAVE_newversion', undef );
    return $page->save_version;
}

1;

__END__

