# 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: Themes.pm 3233 2008-08-21 12:47:26Z josh $

package BigMed::App::Web::Themes;
use Carp;
$Carp::Verbose = 1;
use strict;
use utf8;
use base qw(BigMed::App::Web::CP);
use BigMed::Theme;
use BigMed::CSS;
use BigMed::DiskUtil qw(bm_file_path bm_copy_file bm_copy_dir);

sub setup {
    my $app = shift;
    $app->start_mode('menu');
    $app->set_cp_selected_nav('Layout');
    $app->run_modes(
        'AUTOLOAD'  => sub { $_[0]->rm_menu() },
        'menu' => 'rm_menu',
        'new-first-theme' => 'rm_new_first_theme',
        'first-theme' => 'rm_first_theme',
        
        'preview' => 'rm_preview',
        'first-preview' => 'rm_first_preview',
        'new-first-preview' => 'rm_new_first_preview',
        
        'apply' => 'rm_apply',
        'first-apply' => 'rm_first_apply',
        
        'edit' => 'rm_edit',
        'save' => 'rm_save',
        'remove' => 'rm_remove',
        'do-remove' => 'rm_do_remove',
        'save-site' => 'rm_save_site',
        'add-library' => 'rm_add_library',
        'ajax-check-slug' => 'rm_ajax_check_slug',
    );
}

my %category_names;

sub cgiapp_prerun {
    my $app = shift;
    $app->SUPER::cgiapp_prerun;
    $app->require_privilege_level(5);

    %category_names = (
        '_general' => $app->language('THEME_CAT_general'),
        '_custom' => $app->language('THEME_CAT_custom'),
    );
}

###########################################################
# RUN MODES
###########################################################

sub rm_first_theme { #for first site ever
    my $app = shift;
    my %options = @_;
    $options{head}        ||= 'THEMES_Choose a Design Theme';
    $options{template}    ||= 'screen_themes_first-theme.tmpl';
    $options{message}    ||= 'THEMES_First theme message';
    $options{first_time} = 1;
    $options{rm_prefix} = 'first';
    $app->rm_menu(%options);
}

sub rm_new_first_theme { #for other new sites
    my $app = shift;
    my %options = @_;
    $options{head}        ||= 'THEMES_Choose a Design Theme';
    $options{message}    ||= 'THEMES_First theme message';
    $options{first_time} = 1;
    $options{rm_prefix} = 'new-first';
    $app->rm_menu(%options);
}

sub rm_menu {
    my $app = shift;
    my %options = @_;
    my $site = $app->current_site or return $app->rm_login_site;
    my $site_id = $site->id;
    my ($want_cat) = $app->path_args;
    $want_cat ||= '_custom';
    my $theme = BigMed::Theme->new();

    #collect theme tabs
    my @categories = $theme->categories;
    my $selected;
    foreach my $c (@categories) {
        $selected = $c, last if $c eq $want_cat;
    }
    $selected ||= $categories[0];
    my $menu_rm = $options{rm_prefix} ? "$options{rm_prefix}-theme" :  'menu';
    my @tabs = map {
        {   text => $category_names{$_} || $_,
            selected => $_ eq $selected,
            url => $app->build_url(
                script => 'bm-themes.cgi',
                rm     => $menu_rm,
                site   => $site_id,
                args   => [$_],
            ),
        }
    } @categories;

    #collect category themes
    my $preview_rm =
      $options{rm_prefix} ? "$options{rm_prefix}-preview" : 'preview';
    my @themes;
    if ($selected) {
        my $default_thumb = $app->env('BMADMINURL')
          . '/img/bmcp_default_theme.jpg';
        @themes = $theme->themes($selected);
        my $base_preview = $app->build_url(
            script => 'bm-themes.cgi',
            rm     => $preview_rm,
            site   => $site_id
        );
        my $base_select = $app->build_url(
            script => 'bm-themes.cgi',
            rm     => $options{first_time} ? 'first-apply' : 'apply',
            site   => $site_id
        );
        foreach my $th ( @themes ) {
            $th->{select_url} = "$base_select/$selected/" . $th->{theme},
            $th->{preview_url} = "$base_preview/$selected/" . $th->{theme},
            $th->{name} = $app->escape($th->{name});
            $th->{first_time} = $options{first_time};
            $th->{thumbnail} ||= $default_thumb;
        }
    }

    #page title and message
    my $title_unlocal = $options{head} || 'THEMES_New Theme';
    my ( $title, $message ) = $app->title_and_message(
        field_msg => $options{field_msg},
        message   => $options{message} || 'THEMES_theme_intro',
        title     => $title_unlocal,
    );

    $app->_set_breadcrumbs(
        {   bc_label => [
                'THEMES_Category Edit Menu',
                ( $category_names{$selected} || $selected )
            ]
        }
    );

    $app->js_add_script( $app->env('BMADMINURL') . '/js/bm-theme.js' );
    
    my $template = $options{template} || 'screen_themes_menu.tmpl';
    $app->html_template_screen(
        $template,
        bmcp_title => $title,
        message    => $message,
        tabs => \@tabs,
        themes => \@themes,
        step6 => $options{first_time},                            #for setup wizard
    );
}

sub rm_first_preview {
    my $app = shift;
    my %options = @_;
    $options{template}    ||= 'screen_themes_first-preview.tmpl';
    $options{first_time} = 1;
    $options{rm_prefix} = 'first';
    $options{prev_rm} = 'rm_first_theme';
    $app->rm_preview(%options);
}

sub rm_new_first_preview {
    my $app = shift;
    my %options = @_;
    $options{first_time} = 1;
    $options{rm_prefix} = 'new-first';
    $options{prev_rm} = 'rm_new_first_theme';
    $app->rm_preview(%options);
}


sub rm_preview {
    my $app = shift;
    my %options = @_;
    my $site = $app->current_site or return $app->rm_login_site;
    my $site_id = $site->id;
    my ($category, $detail) = $app->path_args;
    
    my $theme = BigMed::Theme->new();
    my %info = $theme->theme_metadata( $category, $detail );
    my $prev_rm = $options{prev_rm} || 'rm_menu';
    if (!%info) {
        $app->set_error(
            head => 'THEME_Could not load theme',
            text => ['THEME_TEXT_Could not load theme', $detail, $category]
        );
        return $app->$prev_rm();
    }

    #page title and message
    my $title_unlocal = $options{head} || ['THEMES_Theme Info', $info{name}];
    my ( $title, $message ) = $app->title_and_message(
        field_msg => $options{field_msg},
        message   => $options{message},
        title     => $title_unlocal,
    );

    my $select_url = $app->build_url(
        script => 'bm-themes.cgi',
        rm     => $options{first_time} ? 'first-apply' : 'apply',
        site   => $site_id,
        args   => [$category,$detail],
    );
    my $menu_url = $app->build_url(
        script => 'bm-themes.cgi',
        rm     => $options{rm_prefix} ? "$options{rm_prefix}-theme" : 'menu',
        site   => $site_id,
        args   => [$category],
    );
    $app->_set_breadcrumbs(
        {   bc_label => [
                'THEMES_Category Edit Menu',
                ( $category_names{$category} || $category )
            ],
            bc_url => $menu_url,
        },
        {   bc_label => ['THEMES_Theme Info', $info{name}],
        }
    );
    
    $app->js_add_script( $app->env('BMADMINURL') . '/js/bm-theme.js' );
    
    my $template = $options{template} || 'screen_themes_preview.tmpl';
    $app->html_template_screen(
        $template,
        bmcp_title => $title,
        message    => $message,
        %info,
        category => $category,
        theme => $detail,
        menu_url => $menu_url,
        select_url => $select_url,
        step6 => $options{first_time},
    );
}

sub rm_first_apply {
    my $app = shift;
    my %options = @_;
    $options{first_time} = 1;
    $options{rm_menu} = 'rm_first_preview';
    $app->rm_apply(%options);
}

sub rm_apply {
    my $app = shift;
    my %options = @_;
    my $rm_menu = $options{rm_menu} || 'rm_menu';
    $app->require_post() or return $app->$rm_menu;
    my $site = $app->current_site;
    my ( $category, $theme_name ) = $app->path_args();

    my $theme = BigMed::Theme->new();
    my %info = $theme->theme_metadata( $category, $theme_name );
    if ( !%info ) {    #no such theme
        $app->set_error(
            head => 'THEME_Could not load theme',
            text => ['THEME_TEXT_Could not load theme', $theme_name, $category]
        );
        return $app->$rm_menu();
    }
    $theme->apply_theme( $site, $category, $theme_name )
      or return $app->$rm_menu;
    BigMed::CSS->build_sheet($site) or return $app->$rm_menu;

    if ($options{first_time}) {
        #all done with setting up a new site; generate its pages
        #and bump over to the editor with a greeting
        require BigMed::Builder;
        my $builder = BigMed::Builder->new( site => $site )
          or return $app->$rm_menu();
        $builder->build()
          or return $app->$rm_menu();

        $app->set_session_message(
            [   'THEMES_Site Configuration Complete',
                $site->homepage_url . '/index.shtml'
            ]
        );
        $app->header_type('redirect');
        $app->header_props(
            -url => $app->build_url(
                script => 'bm-editor.cgi',
                rm     => 'menu',
                site   => $site->id,
            )
        );
        return 'Redirecting...';
    }
    else {
        my $b_url = $app->build_url(
            script => 'bm-build.cgi',
            rm     => 'build-all',
            site   => $site->id,
        );
        return $app->$rm_menu(
            message => ['THEME_The theme has been applied', $info{name}, $b_url] );
    }
}

sub rm_edit {
    my $app = shift;
    my %options = @_;
    my $theme = BigMed::Theme->new();
    my $site = $app->current_site;
    my $css = $app->escape( $theme->site_css_text( $site ) );

    my $field = $app->prompt_field_ref(
        id         => 'theme_css',
        prompt_as  => 'raw_text',
        value      => $css,
        hide_label => 1,
        width      => '98%',
        height     => '18em',
        css_class  => 'bmcpMarkup',
        label      => 'THEME_Theme Style Sheet',
    );
    my $submit = $app->prompt_field_ref(
        id        => 'theme_submit',
        prompt_as => 'submit',
        value     => $app->language('BM_SUBMIT_LABEL_Save'),
    );
    my $fieldset = $app->prompt_fieldset_ref(
        id     => 'bmfs_template',
        fields => [$field, $submit],
        title  => 'THEME_Theme Style Sheet',
        query     => $options{query},
        field_msg => $options{field_msg},
        help =>  'THEME_What is theme CSS?',
    );

    my $form_url = $app->build_url(
        script => 'bm-themes.cgi',
        site   => $site->id,
        rm     => 'save',
    );
    
    my ( $title, $message ) = $app->title_and_message(
        title     => 'THEME_Edit Theme CSS',
        message => $options{message},
        field_msg => $options{field_msg},
    );
    $app->_set_breadcrumbs( { bc_label => 'THEME_Edit Theme CSS' } );
    
    $app->html_template_screen(
        'screen_cp_generic.tmpl',
        bmcp_title => $title,
        form_url   => $form_url,
        message    => $message,
        fieldsets  => [$fieldset],
    );
}

sub rm_save {
    my $app   = shift;
    my $site = $app->current_site;
    my %field = $app->parse_submission(
        {   id       => 'theme_css',
            parse_as => 'raw_text',
        }
    );
    return $app->rm_edit(
        query     => $app->query,
        field_msg => $field{_ERROR},
      )
      if $field{_ERROR};

    my $theme = BigMed::Theme->new();
    $theme->save_site_css( $site, $field{theme_css} )
      or return $app->rm_edit( query => $app->query );
    BigMed::CSS->build_sheet($site) or return $app->rm_menu;
    $app->rm_edit( message => 'THEME_CSS saved' );
}

sub rm_remove {
    my $app = shift;
    my $site_id = $app->current_site->id;
    
    my $remove_url = $app->build_url(
        script => 'bm-themes.cgi',
        rm     => 'do-remove',
        site   => $site_id,
    );
    my $menu_url = $app->build_url(
        script => 'bm-themes.cgi',
        rm     => 'menu',
        site   => $site_id,
    );
    my $tmpl_url = $app->build_url(
        script => 'bm-templates.cgi',
        rm     => 'menu',
        site   => $site_id,
    );
    my $edit_url = $app->build_url(
        script => 'bm-themes.cgi',
        rm     => 'edit',
        site   => $site_id,
    );

    my ( $title, $message ) = $app->title_and_message(
        message   => ['THEME_About theme removal', $menu_url, $tmpl_url, $edit_url],
        title     => 'THEME_Remove Design Theme',
    );
    $app->_set_breadcrumbs( { bc_label => 'THEME_Remove Design Theme' } );
    
    $app->js_add_script( $app->env('BMADMINURL') . '/js/bm-theme.js' );
    $app->html_template_screen(
        'screen_themes_remove.tmpl',
        bmcp_title => $title,
        message    => $message,
        remove_url => $remove_url,
    );
}

sub rm_do_remove {
    my $app = shift;
    my $site = $app->current_site;
    $app->require_post() or return $app->rm_remove;
    my $theme = BigMed::Theme->new();
    $theme->clear_site_theme( $site ) or return $app->rm_remove;
    BigMed::CSS->build_sheet($site) or return $app->rm_menu;
    $app->rm_menu( message => 'THEME_Theme was removed' );
}

sub rm_save_site {
    my $app = shift;
    my %options = @_;
    my $user = $app->current_user;
    return $app->rm_not_permitted if !$user || $user->level < 6;
    my $site = $app->current_site;
    my @fieldsets;
    
    my $slug = _scrub_theme_slug( lc $site->name );
    $slug = 'my-theme' if !$slug;
    
    my $theme = BigMed::Theme->new();
    my $bmtheme_dir = $theme->site_asset_path($site);
    my $bmtheme_url;
    if (-e $bmtheme_dir) {
        $bmtheme_url = $site->html_url . '/bm.theme';
    }
    else {
        undef $bmtheme_dir;
    }
    my $example_url = $site->homepage_url . '/images';

    #description fieldset
    my $fname = $app->prompt_field_ref(
        id         => 'theme_name',
        prompt_as  => 'simple_text',
        label      => 'THEME_Theme Name',
        required   => 1,
        value => $site->name,
    );
    my $fslug = $app->prompt_field_ref(
        id         => 'theme_slug',
        prompt_as  => 'url_safe',
        value => $slug,
        label      => 'THEME_Theme Slug',
        description      => 'THEME_DESC_Theme Slug',
        required   => 1,
    );
    push @fieldsets, $app->prompt_fieldset_ref(
        id     => 'bmfs_title',
        fields => [$fname, $fslug],
        title  => 'THEME_Theme Title',
        query     => $options{query},
        field_msg => $options{field_msg},
    );

    my $fdesc = $app->prompt_field_ref(
        id          => 'theme_description',
        prompt_as   => 'rich_text_brief',
        label       => 'THEME_Theme Description',
        description => 'THEME_DESC_Theme Description',
    );
    my $fscreen = $app->prompt_field_ref(
        id         => 'theme_screenshot',
        prompt_as  => 'document',
        label      => 'THEME_Screenshot',
        description => 'THEME_DESC_Screenshot',
    );
    my $fpreview = $app->prompt_field_ref(
        id         => 'theme_thumbnail',
        prompt_as  => 'document',
        label      => 'THEME_Preview',
        description => 'THEME_DESC_Preview',
    );
    push @fieldsets, $app->prompt_fieldset_ref(
        id     => 'bmfs_description',
        fields => [$fscreen, $fpreview, $fdesc],
        title  => 'THEME_Theme Summary',
        query     => $options{query},
        field_msg => $options{field_msg},
    );

    #asset directory fieldset
    my $fasseturl = $app->prompt_field_ref(
        id         => 'theme_asseturl',
        prompt_as  => 'dir_url',
        label      => 'THEME_Asset URL',
        value      => $bmtheme_url,
    );
    my $fassetdir = $app->prompt_field_ref(
        id         => 'theme_assetdir',
        prompt_as  => 'dir_path',
        label      => 'THEME_Asset Directory',
        ajax_status => 1,
        value      => $bmtheme_dir,
    );
    push @fieldsets, $app->prompt_fieldset_ref(
        id     => 'bmfs_assets',
        fields => [$fasseturl, $fassetdir],
        title  => 'THEME_Image & Asset Directory',
        query     => $options{query},
        field_msg => $options{field_msg},
        pre_html => $app->language(['THEME_Asset directory description', $example_url]),
        optional => 1,
    );

    #author fieldset
    my $fauthor = $app->prompt_field_ref(
        id         => 'theme_author',
        prompt_as  => 'simple_text',
        label      => 'THEME_Author Name',
    );
    my $femail = $app->prompt_field_ref(
        id         => 'theme_email',
        prompt_as  => 'email',
        label      => 'THEME_Author Email',
    );
    my $furl = $app->prompt_field_ref(
        id         => 'theme_url',
        prompt_as  => 'url',
        label      => 'THEME_Author URL',
        value      => 'http://',
    );
    push @fieldsets, $app->prompt_fieldset_ref(
        id     => 'bmfs_author',
        fields => [$fauthor, $femail, $furl],
        title  => 'THEME_Author Info',
        query     => $options{query},
        field_msg => $options{field_msg},
        optional => 1,
    );
    
    #save button
    my $submit = $app->prompt_field_ref(
        id        => 'theme_submit',
        prompt_as => 'submit',
        value     => $app->language('BM_SUBMIT_LABEL_Save'),
    );
    my $checked = $app->prompt_field_ref(
        id        => 'theme_checked',
        prompt_as => 'hidden',
        value     => q{},
    );
    push @fieldsets, $app->prompt_fieldset_ref( fields => [$submit,$checked] );
    
    my $form_url = $app->build_url(
        script => 'bm-themes.cgi',
        site   => $site->id,
        rm     => 'add-library',
    );
    
    $app->js_add_script( $app->env('BMADMINURL') . '/js/bm-theme.js' );
    $app->js_add_script( $app->env('BMADMINURL') . '/js/bm-config.js' );
    my ( $title, $message ) = $app->title_and_message(
        title     => 'THEME_Save to Theme Library',
        message => $options{message} || ['THEME_INTRO_Save to Theme Library',$site->name],
        field_msg => $options{field_msg},
    );
    $app->_set_breadcrumbs( { bc_label => 'THEME_Save to Theme Library' } );

    return $app->html_template_screen(
        'screen_cp_generic.tmpl',
        bmcp_title => $title,
        form_url   => $form_url,
        form_id    => 'form_save-to-library',
        message    => $message,
        fieldsets  => \@fieldsets,
    );
}

sub rm_add_library {
    my $app = shift;
    my $user = $app->current_user;
    return $app->rm_not_permitted if !$user || $user->level < 6;
    my $site = $app->current_site;

    my %field = $app->parse_submission(
        {   id       => 'theme_name',
            parse_as => 'simple_text',
            required => 1,
        },
        {   id       => 'theme_slug',
            parse_as => 'url_safe',
            required => 1,
        },
        {
            id         => 'theme_description',
            parse_as  => 'rich_text_brief',
        },
        {   id         => 'theme_screenshot',
            parse_as  => 'document',
        },
        {   id         => 'theme_thumbnail',
            parse_as  => 'document',
        },
        {
            id         => 'theme_asseturl',
            parse_as  => 'dir_url',
        },
        {        
            id         => 'theme_assetdir',
            parse_as  => 'dir_path',
        },
        {
            id         => 'theme_author',
            parse_as  => 'simple_text',
        },
        {
            id         => 'theme_email',
            parse_as  => 'email',
        },
        {
            id         => 'theme_url',
            parse_as  => 'url',
        }
    );
    return $app->rm_save_site(
        query     => $app->query,
        field_msg => $field{_ERROR},
      )
      if $field{_ERROR};
    
    $field{theme_slug} = _scrub_theme_slug($field{theme_slug});
    #check asset directory
    if ($field{theme_assetdir}) {
        if (!-e $field{theme_assetdir}) {
            $field{_ERROR}->{theme_assetdir} =
              'THEME_Asset directory does not exist';
        }
        elsif (!$field{theme_asseturl}) {
            $field{_ERROR}->{theme_asseturl} =
              'THEME_Supply both URL and path for asset directory';
        }
    }
    elsif ($field{theme_asseturl}) {
        $field{_ERROR}->{theme_assetdir} =
          'THEME_Supply both URL and path for asset directory';
    }
    return $app->rm_save_site(
        query     => $app->query,
        field_msg => $field{_ERROR},
      )
      if $field{_ERROR};


    #collect data and save it
    require BigMed::Filter;
    my %meta;
    $field{theme_description} =
      BigMed::Filter->inline_single_graf(
        BigMed::Filter->filter( $field{theme_description} ) );

    foreach my $key (qw(name description author email url)) {
        my $value = $field{"theme_$key"};
        $meta{$key} = $value if $value ne q{};
    }
    my $theme = BigMed::Theme->new();
    $theme->save_site_to_library($site, '_custom', $field{theme_slug}, \%meta)
      or return $app->rm_save_site( query => $app->query );
    $app->log( warning => 'Themes: '
      . $app->log_data_tag($user)
      . " saved theme $field{theme_slug} to library" );


    #update templates and themes to use url
    if ($field{theme_asseturl}) {
        $theme->update_asset_url( $site, '_custom', $field{theme_slug},
            $field{theme_asseturl} )
          or return $app->rm_save_site( query => $app->query );
    }
    
    #import non-directory files from theme
    if ( $field{theme_assetdir} ) {
        $theme->import_theme_assets( '_custom', $field{theme_slug},
            $field{theme_assetdir} )
          or return $app->rm_save_site( query => $app->query );
    }

    #save the screenshots, or leave any existing ones
    my $detail_dir = $theme->detail_dir('_custom', $field{theme_slug});
    foreach my $itype (qw(screenshot thumbnail)) {
        my $rinfo = $field{"theme_$itype"} or next;
        my ( $filename, $path, $FILE ) = @{$rinfo};
        next if !$filename; #no file provided
        
        my ($suffix) = ( $filename =~ /[.](jpg|gif|png|jpeg)$/msi );
        if ( !$suffix ) {    #not one of our filetypes
            close $FILE if $FILE;
            next;
        }
        $suffix = lc $suffix;
        my $final_path = bm_file_path( $detail_dir, "$itype.$suffix" );
        bm_copy_file( $path, $final_path ) or return;
        close $FILE if $FILE;

        require BigMed::Media::Image;
        if ( BigMed::Media::Image->can_thumbnail ) {
            my $width  = $itype eq 'screenshot' ? '600' : '100';
            my $height = $itype eq 'screenshot' ? '400' : '100';
            my $method = $itype eq 'screenshot' ? '_do_squeeze' : '_do_squeeze_crop';
            #if there's a problem, just continue, leaving orig in place
            BigMed::Media::Image->$method(
                filepath => $final_path,
                type     => ( $suffix eq 'jpg' ? 'jpeg' : $suffix ),
                formats => [[$width, $height, $final_path]],
                driver => BigMed::Media::Image->driver,
            );
        }
    }
    
    #backup the custom themes directory
    my $backup_dir = bm_file_path( $app->env('MOXIEDATA'),
        'templates_custom', 'theme_backup' );
    bm_copy_dir( $theme->category_dir('_custom'),
        $backup_dir, { build_path => 1, data => 1 } )
      or return $app->rm_save_site( query => $app->query );
    $app->log( info => 'Themes: custom themes backed up' );

    #flip back to the theme menu with confirmation message
    $app->set_session_message('BM_Your changes have been saved.');
    $app->header_type('redirect');
    $app->header_props(
        -url => $app->build_url(
            script => 'bm-themes.cgi',
            rm     => 'menu',
            args   => ['_custom'],
        )
    );
    return 'Redirecting...';
}

sub rm_ajax_check_slug {
    my $app = shift;
    my $user = $app->current_user;
    return $app->rm_not_permitted if !$user || $user->level < 6;
    my $site = $app->current_site;

    my ($slug) = _scrub_theme_slug( $app->path_args );
    if ( !defined $slug || $slug eq q{}) {
        $app->set_error(
            head => 'THEMES_Invalid Slug Name',
            text => 'THEMES_TEXT_Invalid Slug Name',
        );
        return $app->ajax_system_error();
    }

    my $theme = BigMed::Theme->new();
    my $cat_dir =
      $theme->category_dir( '_custom', { build_path => 1 } )
      or return $app->ajax_system_error();
    my $detail_dir = bm_file_path($cat_dir, $slug);
    my %response = ( 'avail' => (-e $detail_dir ? undef : 'ok') );
    if (!$response{avail}) {
        my %meta = $theme->theme_metadata('_custom', $slug);
        $response{taken} = $meta{name} || $app->language('BM_Untitled');
    }
    return $app->ajax_data(\%response);
}

sub _scrub_theme_slug {
    my $slug = shift;
    $slug = q{} if !defined $slug;
    $slug =~ s/\s+/-/msg;
    $slug =~ s/[^A-Za-z\-_]//msg;
    if ( length $slug > 50 ) {
        $slug = substr($slug, 0, 50);
    }
    return $slug;
}

sub _set_breadcrumbs {
    my ($app, @crumbs) = @_;
    my @bc = (
        {   bc_label => 'BM_CP_NAVLABEL_Layout',
            bc_url   => $app->build_url(
                script => 'bm-templates.cgi',
                rm     => 'main-menu',
                site   => $app->current_site->id,
            ),
        },
        @crumbs,
    );
    $app->set_cp_breadcrumbs(@bc);
}


1;

__END__