Changeset 1369

Show
Ignore:
Timestamp:
02/14/08 21:09:26 (7 months ago)
Author:
bchoate
Message:

Broke CMS into smaller parts to reduce memory footprint and group code into logical parts. BugId:58666

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • branches/release-30/lib/MT/App.pm

    r1366 r1369  
    532532    if ($ENV{MOD_PERL}) { 
    533533        if ($app->{response_message}) { 
    534             $app->{apache}->status_line(($app->response_code || 200) . " "  
    535                                         . $app->{response_message}); 
     534            $app->{apache}->status_line(($app->response_code || 200) 
     535                                        . ($app->{response_message} ? ' ' . $app->{response_message} : ''); 
    536536        } else { 
    537537            $app->{apache}->status($app->response_code || 200); 
     
    613613    if ($MT::DebugMode & 128) { 
    614614        MT->add_callback('pre_run', 1, $app, sub { $app->pre_run_debug }); 
    615         MT->add_callback('post_run', 1, $app, sub { $app->post_run_debug }); 
     615        MT->add_callback('takedown', 1, $app, sub { $app->post_run_debug }); 
    616616    } 
    617617    $app->{vtbl} = $app->registry("methods"); 
     
    20722072        } 
    20732073 
     2074        my $mode = $app->mode || 'default'; 
     2075 
    20742076        REQUEST: 
    20752077        { 
    20762078            my $requires_login = $app->{requires_login}; 
    2077  
    2078             my $mode = $app->mode || 'default'; 
    20792079 
    20802080            my $code = $app->handlers_for_mode($mode); 
     
    21612161                    my @forward_params = @{ $app->{forward_params} } 
    21622162                        if $app->{forward_params}; 
     2163                    $app->{forward_params} = undef; 
    21632164                    my $content = $code->($app, @forward_params); 
    21642165                    $app->response_content($content) 
     
    21702171 
    21712172            if (my $new_mode = $app->{forward}) { 
    2172                 $app->mode($new_mode, @{ $app->{forward_params} || [] })
     2173                $mode = $new_mode
    21732174                goto REQUEST; 
    21742175            } 
  • branches/release-30/lib/MT/App/CMS.pm

    r1363 r1369  
    1010use base qw( MT::App ); 
    1111 
    12 use Symbol; 
    13 use File::Spec; 
    14 use MT::Util qw( encode_html format_ts offset_time_list offset_time epoch2ts 
    15   remove_html get_entry mark_odd_rows first_n_words 
    16   perl_sha1_digest_hex is_valid_email relative_date ts2epoch 
    17   perl_sha1_digest encode_url dirify encode_js is_valid_date 
    18   archive_file_for is_url ); 
    19 use MT::I18N qw( substr_text const length_text wrap_text encode_text 
    20   break_up_text first_n_text guess_encoding ); 
    21 use CGI; 
     12use MT::Util qw( format_ts epoch2ts perl_sha1_digest_hex perl_sha1_digest 
     13    remove_html ); 
    2214 
    2315use constant LISTING_DATE_FORMAT      => '%b %e, %Y'; 
    2416use constant LISTING_DATETIME_FORMAT  => '%b %e, %Y'; 
    2517use constant LISTING_TIMESTAMP_FORMAT => "%Y-%m-%d %I:%M:%S%p"; 
     18use constant NEW_PHASE => 1; 
    2619 
    2720sub id { 'cms' } 
     
    4437sub core_methods { 
    4538    my $app = shift; 
     39    my $pkg = '$Core::MT::CMS::'; 
    4640    return { 
    47         'tools'     => \&tools
    48         'dashboard' => \&dashboard
    49         'menu'      => \&dashboard
    50         'admin'     => \&dashboard
     41        'tools'     => "${pkg}Tools::system_check"
     42        'dashboard' => "${pkg}Dashboard::dashboard"
     43        'menu'      => '${pkg}Dashboard::dashboard'
     44        'admin'     => '${pkg}Dashboard::dashboard'
    5145 
    5246        ## Generic handlers 
    53         'save'           => \&save_object
    54         'edit'           => \&edit_object
    55         'view'           => \&edit_object
    56         'list'           => \&list_objects
    57         'delete'         => \&delete
    58         'search_replace' => \&search_replace
     47        'save'           => "${pkg}Common::save"
     48        'edit'           => "${pkg}Common::edit"
     49        'view'           => "${pkg}Common::edit"
     50        'list'           => "${pkg}Common::list"
     51        'delete'         => "${pkg}Common::delete"
     52        'search_replace' => "${pkg}Search::search_replace"
    5953 
    6054        ## Edit methods 
    61         'edit_role' => \&edit_role
     55        'edit_role' => "${pkg}User::edit_role"
    6256 
    6357        ## Listing methods 
    64         'list_ping'     => \&list_pings
    65         'list_entry'    => \&list_entries
    66         'list_template' => \&list_template
    67         'list_page'     => \&list_pages
     58        'list_ping'     => "${pkg}TrackBack::list"
     59        'list_entry'    => "${pkg}Entry::list"
     60        'list_template' => "${pkg}Template::list"
     61        'list_page'     => "${pkg}Page::list"
    6862        'list_comment'  => { 
    69             handler    => \&list_comments
     63            handler    => "${pkg}Comment::list"
    7064            permission => 'view_feedback', 
    7165        }, 
    72         'list_member'      => \&list_member
    73         'list_user'        => \&list_authors
    74         'list_author'      => \&list_authors
    75         'list_commenter'   => \&list_commenter
    76         'list_asset'       => \&list_assets
    77         'list_blog'        => \&list_blogs
    78         'list_category'    => \&list_category
    79         'list_tag'         => \&list_tag
    80         'list_association' => \&list_associations
    81         'list_role'        => \&list_roles
    82  
    83         'asset_insert'        => \&asset_insert
    84         'asset_userpic'       => \&asset_userpic
    85         'save_commenter_perm' => \&save_commenter_perm
    86         'trust_commenter'     => \&trust_commenter
    87         'ban_commenter'       => \&ban_commenter
    88         'approve_item'        => \&approve_item
    89         'unapprove_item'      => \&unapprove_item
    90         'preview_entry'       => \&preview_entry
     66        'list_member'      => "${pkg}User::list_member"
     67        'list_user'        => "${pkg}User::list"
     68        'list_author'      => "${pkg}User::list"
     69        'list_commenter'   => "${pkg}Comment::list_commenter"
     70        'list_asset'       => "${pkg}Asset::list"
     71        'list_blog'        => "${pkg}Blog::list"
     72        'list_category'    => "${pkg}Category::list"
     73        'list_tag'         => "${pkg}Tag::list"
     74        'list_association' => "${pkg}User::list_association"
     75        'list_role'        => "${pkg}User::list_role"
     76 
     77        'asset_insert'        => "${pkg}Asset::insert"
     78        'asset_userpic'       => "${pkg}User::asset_userpic"
     79        'save_commenter_perm' => "${pkg}Comment::save_commenter_perm"
     80        'trust_commenter'     => "${pkg}Comment::trust_commenter"
     81        'ban_commenter'       => "${pkg}Comment::ban_commenter"
     82        'approve_item'        => "${pkg}Comment::approve_item"
     83        'unapprove_item'      => "${pkg}Comment::unapprove_item"
     84        'preview_entry'       => "${pkg}Entry::preview"
    9185 
    9286        ## Blog configuration screens 
    93         'cfg_archives'     => \&cfg_archives
    94         'cfg_prefs'        => \&cfg_prefs
    95         'cfg_plugins'      => \&cfg_plugins
    96         'cfg_comments'     => \&cfg_comments
    97         'cfg_trackbacks'   => \&cfg_trackbacks
    98         'cfg_registration' => \&cfg_registration
    99         'cfg_spam'         => \&cfg_spam
    100         'cfg_entry'        => \&cfg_entry
    101         'cfg_web_services' => \&cfg_web_services
     87        'cfg_archives'     => "${pkg}Blog::cfg_archives"
     88        'cfg_prefs'        => "${pkg}Blog::cfg_prefs"
     89        'cfg_plugins'      => "${pkg}Plugin::cfg_plugins"
     90        'cfg_comments'     => "${pkg}Comment::cfg_comments"
     91        'cfg_trackbacks'   => "${pkg}TrackBack::cfg_trackbacks"
     92        'cfg_registration' => "${pkg}Comment::cfg_registration"
     93        'cfg_spam'         => "${pkg}Comment::cfg_spam"
     94        'cfg_entry'        => "${pkg}Entry::cfg_entry"
     95        'cfg_web_services' => "${pkg}Blog::cfg_web_services"
    10296 
    10397        ## Save 
    104         'save_cat'     => \&save_category
    105         'save_entries' => \&save_entries
    106         'save_pages'   => \&save_pages
    107         'save_entry'   => \&save_entry
    108         'save_role'    => \&save_role
     98        'save_cat'     => "${pkg}Category::save"
     99        'save_entries' => "${pkg}Entry::save_entries"
     100        'save_pages'   => "${pkg}Page::save"
     101        'save_entry'   => "${pkg}Entry::save"
     102        'save_role'    => "${pkg}User::save_role"
    109103 
    110104        ## List actions 
    111         'enable_object'  => \&enable_object
    112         'disable_object' => \&disable_object
    113         'list_action'    => \&do_list_action
    114         'empty_junk'     => \&empty_junk
    115         'handle_junk'    => \&handle_junk
    116         'not_junk'       => \&not_junk
    117  
    118         'ping'               => \&send_pings
    119         'rebuild_phase'      => \&rebuild_phase
    120         'rebuild'            => \&rebuild_pages
    121         'rebuild_new_phase'  => \&rebuild_new_phase
    122         'start_rebuild'      => \&start_rebuild_pages
    123         'rebuild_confirm'    => \&rebuild_confirm
    124         'entry_notify'       => \&entry_notify
    125         'send_notify'        => \&send_notify
    126         'start_upload'       => \&start_upload
    127         'upload_file'        => \&upload_file
    128         'upload_userpic'     => \&upload_userpic
    129         'complete_insert'    => \&complete_insert
    130         'complete_upload'    => \&complete_upload
    131         'start_upload_entry' => \&start_upload_entry
     105        'enable_object'  => "${pkg}User::enable"
     106        'disable_object' => "${pkg}User::disable"
     107        'list_action'    => "${pkg}Tools::do_list_action"
     108        'empty_junk'     => "${pkg}Comment::empty_junk"
     109        'handle_junk'    => "${pkg}Comment::handle_junk"
     110        'not_junk'       => "${pkg}Comment::not_junk"
     111 
     112        'ping'               => "${pkg}Entry::send_pings"
     113        'rebuild_phase'      => "${pkg}Blog::rebuild_phase"
     114        'rebuild'            => "${pkg}Blog::rebuild_pages"
     115        'rebuild_new_phase'  => "${pkg}Blog::rebuild_new_phase"
     116        'start_rebuild'      => "${pkg}Blog::start_rebuild_pages"
     117        'rebuild_confirm'    => "${pkg}Blog::rebuild_confirm"
     118        'entry_notify'       => "${pkg}AddressBook::entry_notify"
     119        'send_notify'        => "${pkg}AddressBook::send_notify"
     120        'start_upload'       => "${pkg}Asset::start_upload"
     121        'upload_file'        => "${pkg}Asset::upload_file"
     122        'upload_userpic'     => "${pkg}User::upload_userpic"
     123        'complete_insert'    => "${pkg}Asset::complete_insert"
     124        'complete_upload'    => "${pkg}Asset::complete_upload"
     125        'start_upload_entry' => "${pkg}Asset::start_upload_entry"
    132126        'logout'             => { 
    133127            code           => \&logout, 
     
    135129        }, 
    136130        'start_recover' => { 
    137             code           => \&start_recover
     131            code           => "${pkg}Tools::start_recover"
    138132            requires_login => 0, 
    139133        }, 
    140134        'recover' => { 
    141             code           => \&recover_password
     135            code           => "${pkg}Tools::recover_password"
    142136            requires_login => 0, 
    143137        }, 
    144138 
    145         'view_log'            => \&view_log
    146         'list_log'            => \&view_log
    147         'reset_log'           => \&reset_log
    148         'export_log'          => \&export_log
    149         'export_notification' => \&export_notification
    150         'start_import'        => \&start_import
    151         'start_export'        => \&start_export
    152         'export'              => \&export
    153         'import'              => \&do_import
    154         'pinged_urls'         => \&pinged_urls
    155         'save_entry_prefs'    => \&save_entry_prefs
    156         'save_favorite_blogs' => \&save_favorite_blogs
    157         'reg_file'            => \&reg_file
     139        'view_log'            => "${pkg}Log::view"
     140        'list_log'            => "${pkg}Log::view"
     141        'reset_log'           => "${pkg}Log::reset"
     142        'export_log'          => "${pkg}Log::export"
     143        'export_notification' => "${pkg}AddressBook::export"
     144        'start_import'        => "${pkg}Import::start_import"
     145        'start_export'        => "${pkg}Export::start_export"
     146        'export'              => "${pkg}Export::export"
     147        'import'              => "${pkg}Import::do_import"
     148        'pinged_urls'         => "${pkg}Entry::pinged_urls"
     149        'save_entry_prefs'    => "${pkg}Entry::save_entry_prefs"
     150        'save_favorite_blogs' => "${pkg}Blog::save_favorite_blogs"
     151        'reg_file'            => "${pkg}Tools::reg_file"
    158152        'reg_bm_js'           => { 
    159             code           => \&reg_bm_js
     153            code           => "${pkg}Tools::reg_bm_js"
    160154            requires_login => 0, 
    161155        }, 
    162         'folder_add'               => \&category_add
    163         'category_add'             => \&category_add
    164         'category_do_add'          => \&category_do_add
    165         'cc_return'                => \&cc_return
    166         'reset_blog_templates'     => \&reset_blog_templates
    167         'handshake'                => \&handshake
    168         'itemset_action'           => \&do_list_action
    169         'page_action'              => \&do_page_action
    170         'cfg_system'               => \&cfg_system_general
    171         'cfg_system_users'         => \&cfg_system_users
    172         'cfg_system_feedback'      => \&cfg_system_feedback
    173         'save_plugin_config'       => \&save_plugin_config
    174         'reset_plugin_config'      => \&reset_plugin_config
    175         'save_cfg_system_feedback' => \&save_cfg_system_feedback
    176         'save_cfg_system_general'  => \&save_cfg_system_general
    177         'save_cfg_system_users'    => \&save_cfg_system_users
    178         'update_welcome_message'   => \&update_welcome_message
     156        'folder_add'               => "${pkg}Category::category_add"
     157        'category_add'             => "${pkg}Category::category_add"
     158        'category_do_add'          => "${pkg}Category::category_do_add"
     159        'cc_return'                => "${pkg}Blog::cc_return"
     160        'reset_blog_templates'     => "${pkg}Template::reset_blog_templates"
     161        'handshake'                => "${pkg}Blog::handshake"
     162        'itemset_action'           => "${pkg}Tools::do_list_action"
     163        'page_action'              => "${pkg}Tools::do_page_action"
     164        'cfg_system'               => "${pkg}Tools::cfg_system_general"
     165        'cfg_system_users'         => "${pkg}User::cfg_system_users"
     166        'cfg_system_feedback'      => "${pkg}Comment::cfg_system_feedback"
     167        'save_plugin_config'       => "${pkg}Plugin::save_config"
     168        'reset_plugin_config'      => "${pkg}Plugin::reset_config"
     169        'save_cfg_system_feedback' => "${pkg}Comment::save_cfg_system_feedback"
     170        'save_cfg_system_general'  => "${pkg}Tools::save_cfg_system_general"
     171        'save_cfg_system_users'    => "${pkg}User::save_cfg_system_users"
     172        'update_welcome_message'   => "${pkg}Blog::update_welcome_message"
    179173        'upgrade'                  => { 
    180             code           => \&upgrade
     174            code           => "${pkg}Tools::upgrade"
    181175            requires_login => 0, 
    182176        }, 
    183         'plugin_control'           => \&plugin_control
    184         'recover_profile_password' => \&recover_profile_password
    185         'rename_tag'               => \&rename_tag
    186         'remove_user_assoc'        => \&remove_user_assoc
    187         'revoke_role'              => \&revoke_role
    188         'grant_role'               => \&grant_role
    189         'start_backup'             => \&start_backup
    190         'start_restore'            => \&start_restore
    191         'backup'                   => \&backup
    192         'backup_download'          => \&backup_download
    193         'restore'                  => \&restore
    194         'restore_premature_cancel' => \&restore_premature_cancel
    195         'adjust_sitepath'          => \&adjust_sitepath
    196         'system_check'             => \&system_check
    197         'dialog_refresh_templates' => \&dialog_refresh_templates
    198         'refresh_all_templates'    => \&refresh_all_templates
     177        'plugin_control'           => "${pkg}Plugin::plugin_control"
     178        'recover_profile_password' => "${pkg}User::recover_profile_password"
     179        'rename_tag'               => "${pkg}Tag::rename_tag"
     180        'remove_user_assoc'        => "${pkg}User::remove_user_assoc"
     181        'revoke_role'              => "${pkg}User::revoke_role"
     182        'grant_role'               => "${pkg}User::grant_role"
     183        'start_backup'             => "${pkg}Tools::start_backup"
     184        'start_restore'            => "${pkg}Tools::start_restore"
     185        'backup'                   => "${pkg}Tools::backup"
     186        'backup_download'          => "${pkg}Tools::backup_download"
     187        'restore'                  => "${pkg}Tools::restore"
     188        'restore_premature_cancel' => "${pkg}Tools::restore_premature_cancel"
     189        'adjust_sitepath'          => "${pkg}Tools::adjust_sitepath"
     190        'system_check'             => "${pkg}Tools::system_check"
     191        'dialog_refresh_templates' => "${pkg}Template::dialog_refresh_templates"
     192        'refresh_all_templates'    => "${pkg}Template::refresh_all_templates"
    199193 
    200194        ## Comment Replies 
    201         reply         => \&reply
    202         do_reply      => \&do_reply
    203         reply_preview => \&reply_preview
     195        reply         => "${pkg}Comment::reply"
     196        do_reply      => "${pkg}Comment::do_reply"
     197        reply_preview => "${pkg}Comment::reply_preview"
    204198 
    205199        ## Dialogs 
    206         'dialog_restore_upload'  => \&dialog_restore_upload
    207         'dialog_adjust_sitepath' => \&dialog_adjust_sitepath
    208         'dialog_post_comment'    => \&dialog_post_comment
    209         'dialog_select_weblog'   => \&dialog_select_weblog
    210         'dialog_select_sysadmin' => \&dialog_select_sysadmin
    211         'dialog_grant_role'      => \&dialog_grant_role
     200        'dialog_restore_upload'  => "${pkg}Tools::dialog_restore_upload"
     201        'dialog_adjust_sitepath' => "${pkg}Tools::dialog_adjust_sitepath"
     202        'dialog_post_comment'    => "${pkg}Comment::dialog_post_comment"
     203        'dialog_select_weblog'   => "${pkg}Blog::dialog_select_weblog"
     204        'dialog_select_sysadmin' => "${pkg}User::dialog_select_sysadmin"
     205        'dialog_grant_role'      => "${pkg}User::dialog_grant_role"
    212206 
    213207        ## AJAX handlers 
    214         'delete_map'        => \&delete_map
    215         'add_map'           => \&add_map
    216         'js_tag_check'      => \&js_tag_check
    217         'js_tag_list'       => \&js_tag_list
    218         'convert_to_html'   => \&convert_to_html
    219         'update_list_prefs' => \&update_list_prefs
    220         'js_add_category'   => \&js_add_category
    221         'remove_userpic'    => \&remove_userpic
     208        'delete_map'        => "${pkg}Template::delete_map"
     209        'add_map'           => "${pkg}Template::add_map"
     210        'js_tag_check'      => "${pkg}Tag::js_tag_check"
     211        'js_tag_list'       => "${pkg}Tag::js_tag_list"
     212        'convert_to_html'   => "${pkg}Tools::convert_to_html"
     213        'update_list_prefs' => "${pkg}Tools::update_list_prefs"
     214        'js_add_category'   => "${pkg}Category::js_add_category"
     215        'remove_userpic'    => "${pkg}User::remove_userpic"
    222216 
    223217        # declared in MT::App 
    224218        'update_widget_prefs' => sub { return shift->update_widget_prefs(@_) }, 
    225219 
    226         'js_recent_entries_for_tag' => \&js_recent_entries_for_tag
     220        'js_recent_entries_for_tag' => "${pkg}Tag::js_recent_entries_for_tag"
    227221 
    228222        ## DEPRECATED ## 
    229         'list_pings'    => \&list_pings
    230         'list_entries'  => \&list_entries
    231         'list_pages'    => \&list_pages
     223        'list_pings'    => "${pkg}TrackBack::list"
     224        'list_entries'  => "${pkg}Entry::list"
     225        'list_pages'    => "${pkg}Page::list"
    232226        'list_comments' => { 
    233             handler    => \&list_comments
     227            handler    => "${pkg}Comment::list"
    234228            permission => 'view_feedback', 
    235229        }, 
    236         'list_authors'      => \&list_authors
    237         'list_assets'       => \&list_assets
    238         'list_cat'          => \&list_category
    239         'list_blogs'        => \&list_blogs
    240         'list_associations' => \&list_associations
    241         'list_roles'        => \&list_roles
     230        'list_authors'      => "${pkg}User::list"
     231        'list_assets'       => "${pkg}Asset::list"
     232        'list_cat'          => "${pkg}Category::list"
     233        'list_blogs'        => "${pkg}Blog::list"
     234        'list_associations' => "${pkg}User::list_association"
     235        'list_roles'        => "${pkg}User::list_role"
    242236    }; 
    243237} 
     
    245239sub core_widgets { 
    246240    my $app = shift; 
     241    my $pkg = '$Core::MT::CMS::'; 
    247242    return { 
    248243        new_install => { 
     
    260255            set      => 'main', 
    261256            singular => 1, 
    262             handler  => \&new_version_widget
     257            handler  => "${pkg}Dashboard::new_version_widget"
    263258        }, 
    264259        this_is_you => { 
    265260            label    => 'This is You', 
    266261            template => 'widget/this_is_you.tmpl', 
    267             handler  => \&this_is_you_widget
     262            handler  => "${pkg}Dashboard::this_is_you_widget"
    268263            set      => 'sidebar', 
    269264            singular => 1, 
     
    278273            label    => 'Movable Type News', 
    279274            template => 'widget/mt_news.tmpl', 
    280             handler  => \&mt_news_widget
     275            handler  => "${pkg}Dashboard::mt_news_widget"
    281276            singular => 1, 
    282277            set      => 'sidebar', 
     
    285280            label    => 'Blog Stats', 
    286281            template => 'widget/blog_stats.tmpl', 
    287             handler  => \&mt_blog_stats_widget
     282            handler  => "${pkg}Dashboard::mt_blog_stats_widget"
    288283            singular => 1, 
    289284            set      => 'main', 
     
    294289sub core_blog_stats_tabs { 
    295290    my $app = shift; 
     291    my $pkg = '$Core::MT::CMS::'; 
    296292    return { 
    297293        entry => { 
    298294            label    => 'Entries', 
    299295            template => 'widget/blog_stats_entry.tmpl', 
    300             handler  => \&mt_blog_stats_widget_entry_tab
    301             stats    => \&generate_dashboard_stats_entry_tab
     296            handler  => "${pkg}Dashboard::mt_blog_stats_widget_entry_tab"
     297            stats    => "${pkg}Dashboard::generate_dashboard_stats_entry_tab"
    302298        }, 
    303299        comment => { 
    304300            label    => 'Comments', 
    305301            template => 'widget/blog_stats_comment.tmpl', 
    306             handler  => \&mt_blog_stats_widget_comment_tab
    307             stats    => \&generate_dashboard_stats_comment_tab
     302            handler  => "${pkg}Dashboard::mt_blog_stats_widget_comment_tab"
     303            stats    => "${pkg}Dashboard::generate_dashboard_stats_comment_tab"
    308304        }, 
    309305        tag_cloud => { 
     
    327323            refresh_global_templates => { 
    328324                label => "Refresh Global Templates", 
    329                 code => sub { 
    330                     MT->app->refresh_all_templates(@_); 
    331                 }, 
     325                handler => '$Core::MT::CMS::Template::refresh_all_templates', 
    332326                condition => sub { 
    333327                    ! MT->app->blog, 
     
    338332        }, 
    339333    }; 
    340 } 
    341 sub js_recent_entries_for_tag { 
    342     my $app          = shift; 
    343     my $user         = $app->user or return; 
    344     my $tag_class    = $app->model('tag') or return; 
    345     my $objtag_class = $app->model('objecttag') or return; 
    346     my $limit        = $app->param('limit') || 10; 
    347     my $obj_ds       = $app->param('_type') || 'entry'; 
    348     my $blog_id      = $app->param('blog_id'); 
    349     my $obj_class    = $app->model($obj_ds) or return; 
    350     my $tag_name     = $app->param('tag') or return; 
    351     if ( 'utf-8' ne lc( $app->config->PublishCharset) ) { 
    352         $tag_name = MT::I18N::encode_text( $tag_name, 'utf-8', $app->config->PublishCharset ); 
    353     } 
    354     my $tag_obj = 
    355       $tag_class->load( { name => $tag_name }, { binary => { name => 1 } } ); 
    356  
    357     if ( !$tag_obj ) { 
    358         return $app->json_error( $app->translate("Invalid request.") ); 
    359     } 
    360     my $tag_id = $tag_obj->id; 
    361  
    362     my @entries = $obj_class->load( 
    363         { 
    364             ( $blog_id ? ( blog_id => $blog_id ) : () ), 
    365             status => MT::Entry::RELEASE(), 
    366         }, 
    367         { 
    368             sort      => 'authored_on', 
    369             direction => 'descend', 
    370             limit     => $limit, 
    371             join      => $objtag_class->join_on( 
    372                 'object_id', 
    373                 { 
    374                     ( $blog_id ? ( blog_id => $blog_id ) : () ), 
    375                     tag_id            => $tag_id, 
    376                     object_datasource => $obj_ds, 
    377                 } 
    378             ), 
    379         } 
    380     ); 
    381     my $count = 
    382       $obj_class->tagged_count( $tag_id, 
    383         { ( $blog_id ? ( blog_id => $blog_id ) : () ) } ); 
    384     require MT::Template; 
    385     require MT::Blog; 
    386     my $tmpl = $app->load_tmpl('widget/blog_stats_recent_entries.tmpl'); 
    387     my $ctx  = $tmpl->context; 
    388     $ctx->stash( 'blog', MT::Blog->load($blog_id) ) if $blog_id; 
    389     $ctx->stash( 'entries', \@entries ); 
    390     $tmpl->param( 'entry_count', scalar @entries ); 
    391     $tmpl->param( 'script_url', $app->uri ); 
    392     $tmpl->param( 'tag',        $tag_name ); 
    393     $tmpl->param( 'blog_id',    $blog_id ) if $blog_id; 
    394     my $editable = $app->user->is_superuser; 
    395     if ( $blog_id && !$editable ) { 
    396         $editable = $user->permissions($blog_id)->can_edit_all_posts; 
    397     } 
    398     $tmpl->param('editable',    $editable); 
    399     my $html = $app->build_page( $tmpl ); 
    400     return $app->json_result( { html => $html } ); 
    401 } 
    402  
    403 sub js_add_category { 
    404     my $app = shift; 
    405     unless ( $app->validate_magic ) { 
    406         return $app->json_error( $app->translate("Invalid request.") ); 
    407     } 
    408     my $user    = $app->user; 
    409     my $blog_id = $app->param('blog_id'); 
    410     my $perms   = $app->permissions; 
    411     my $type    = $app->param('_type') || 'category'; 
    412     my $class   = $app->model($type); 
    413     if ( !$class ) { 
    414         return $app->json_error( $app->translate("Invalid request.") ); 
    415     } 
    416  
    417     my $label = $app->param('label'); 
    418     my $enc   = $app->config->PublishCharset; 
    419  
    420     # XMLHttpRequest always send text in UTF-8... right? 
    421     if ( 'utf-8' ne lc($enc) ) { 
    422         $label = MT::I18N::encode_text( $label, 'utf-8', $enc ); 
    423     } 
    424     my $basename = $app->param('basename'); 
    425     if ( !defined($label) || ( $label =~ m/^\s*$/ ) ) { 
    426         return $app->json_error( $app->translate("Invalid request.") ); 
    427     } 
    428  
    429     my $blog = $app->blog; 
    430     if ( !$blog ) { 
    431         return $app->json_error( $app->translate("Invalid request.") ); 
    432     } 
    433  
    434     my $parent; 
    435     if ( my $parent_id = $app->param('parent') ) { 
    436         if ( $parent_id != -1 ) {    # special case for 'root' folder 
    437             $parent = $class->load( { id => $parent_id, blog_id => $blog_id } ); 
    438             if ( !$parent ) { 
    439                 return $app->json_error( $app->translate("Invalid request.") ); 
    440             } 
    441         } 
    442     } 
    443  
    444     my $obj      = $class->new; 
    445     my $original = $obj->clone; 
    446  
    447     if ( 
    448         !$app->run_callbacks( 
    449             'cms_save_permission.' . $type, 
    450             $app, $obj, $original 
    451         ) 
    452       ) 
    453     { 
    454         return $app->json_error( $app->translate("Permission denied.") ); 
    455     } 
    456  
    457     $obj->label($label); 
    458     $obj->basename($basename)   if $basename; 
    459     $obj->parent( $parent->id ) if $parent; 
    460     $obj->blog_id($blog_id); 
    461     $obj->author_id( $user->id ); 
    462     $obj->created_by( $user->id ); 
    463  
    464     if ( 
    465         !$app->run_callbacks( 'cms_pre_save.' . $type, $app, $obj, $original ) ) 
    466     { 
    467         return $app->json_error( $app->errstr ); 
    468     } 
    469  
    470     $obj->save; 
    471  
    472     $app->run_callbacks( 'cms_post_save.' . $type, $app, $obj, $original ); 
    473  
    474     return $app->json_result( 
    475         { 
    476             id       => $obj->id, 
    477             basename => $obj->basename 
    478         } 
    479     ); 
    480 } 
    481  
    482 sub convert_to_html { 
    483     my $app    = shift; 
    484     my $format = $app->param('format'); 
    485     my $text   = $app->param('text'); 
    486     # XMLHttpRequest always send text in UTF-8... right? 
    487     if ( defined $text ) { 
    488         $text = encode_text($text, 'utf-8', $app->config->PublishCharset); 
    489     }  
    490     else { 
    491         $text = '' ; 
    492     } 
    493     my $text_more = $app->param('text_more'); 
    494     if ( defined $text_more ) { 
    495         $text_more = encode_text($text_more, 'utf-8', $app->config->PublishCharset); 
    496     }  
    497     else { 
    498         $text_more = '' ; 
    499     } 
    500     my $result = { 
    501         text      => $app->apply_text_filters( $text,      [$format] ), 
    502         text_more => $app->apply_text_filters( $text_more, [$format] ), 
    503         format    => $format, 
    504     }; 
    505     return $app->json_result($result); 
    506 } 
    507  
    508 sub tools { 
    509     my $app = shift; 
    510     $app->system_check; 
    511 } 
    512  
    513 sub system_check { 
    514     my $app = shift; 
    515  
    516     if ( my $blog_id = $app->param('blog_id') ) { 
    517         return $app->redirect( 
    518             $app->uri( 
    519                 'mode' => 'view_log', 
    520                 args => { blog_id => $blog_id } 
    521             ) 
    522         ); 
    523     } 
    524  
    525     my %param; 
    526     # licensed user count: someone who has logged in within 90 days   
    527     my $sess_class = $app->model('session');   
    528     my $from = time - ( 60 * 60 * 24 * 90 + 60 * 60 * 24 );   
    529     $sess_class->remove( 
    530         { kind => 'UA', start => [ undef, $from ] },   
    531         { range => { start => 1 } } 
    532     );   
    533     $param{licensed_user_count} = $sess_class->count( { kind => 'UA' } ); 
    534  
    535     my $author_class = $app->model('author'); 
    536     $param{user_count} = $author_class->count( 
    537         { type => MT::Author::AUTHOR() } ); 
    538  
    539     # commeters: users with only comment permission and MT::Author::COMMENTER 
    540     my $cmntrs = $author_class->count( 
    541         { type => MT::Author::COMMENTER() } ); 
    542  
    543     my @perms = $app->model('permission')->load( 
    544       { 
    545         permissions => "%'comment'%",  
    546         blog_id     => '0', 
    547       }, 
    548       { 
    549         'like' => { 'permissions' => 1 }, 
    550         'not'  => { 'blog_id'     => 1 }, 
    551       } 
    552     ); 
    553     @perms = grep { $_->permissions =~ m/'comment'/ } @perms; 
    554     $param{commenter_count} = scalar(@perms) + $cmntrs; 
    555     $param{screen_id} = "system-check"; 
    556     $param{syscheck_html} = $app->get_syscheck_content() || ''; 
    557      
    558     $app->load_tmpl( 'system_check.tmpl', \%param ); 
    559 } 
    560  
    561 sub get_syscheck_content { 
    562     my $app = shift; 
    563  
    564     my $syscheck_url = $app->base . $app->mt_path . $app->config('CheckScript') . 
    565         '?view=tools&version=' . MT->version_id; 
    566     if ( $syscheck_url && $syscheck_url ne 'disable' ) { 
    567         my $SYSCHECKCACHE_TIMEOUT = 60 * 60 * 24; 
    568         my $sess_class        = $app->model('session'); 
    569         my ($syscheck_object)     = (""); 
    570         my $retries           = 0; 
    571         $syscheck_object = $sess_class->load( { id => 'SC' } ); 
    572         if ( $syscheck_object 
    573             && ( $syscheck_object->start() < ( time - $SYSCHECKCACHE_TIMEOUT ) ) ) 
    574         { 
    575             $syscheck_object->remove; 
    576             $syscheck_object = undef; 
    577         } 
    578         return encode_text( $syscheck_object->data(), 'utf-8', undef ) 
    579           if ($syscheck_object); 
    580  
    581         my $ua = $app->new_ua({ timeout => 20 }); 
    582         return unless $ua; 
    583         $ua->max_size(undef) if $ua->can('max_size'); 
    584  
    585         my $req = new HTTP::Request( GET => $syscheck_url ); 
    586         my $resp = $ua->request($req); 
    587         return unless $resp->is_success(); 
    588         my $result = $resp->content(); 
    589         if ($result) { 
    590             require MT::Sanitize; 
    591  
    592             # allowed html 
    593             my $spec = '* style class id,ul,li,div,span,br,h2,h3,strong,code,blockquote,p'; 
    594             $result = MT::Sanitize->sanitize( $result, $spec ); 
    595             $syscheck_object = MT::Session->new(); 
    596             $syscheck_object->set_values( 
    597                 { 
    598                     id    => 'SC', 
    599                     kind  => 'SC', 
    600                     start => time(), 
    601                     data  => $result 
    602                 } 
    603             ); 
    604             $syscheck_object->save(); 
    605             $result = encode_text( $result, 'utf-8', undef ); 
    606         } 
    607         return $result; 
    608     } 
    609334} 
    610335 
     
    670395sub core_list_actions { 
    671396    my $app = shift; 
     397    my $pkg = '$Core::MT::CMS::'; 
    672398    return { 
    673399        'entry' => { 
     
    675401                label      => "Publish Entries", 
    676402                order      => 100, 
    677                 code       => \&publish_entries
     403                code       => "${pkg}Entry::publish_entries"
    678404                permission => 'edit_all_posts,publish_post', 
    679405                condition  => sub { 
     
    685411                label      => "Unpublish Entries", 
    686412                order      => 200, 
    687                 code       => \&draft_entries
     413                code       => "${pkg}Entry::draft_entries"
    688414                permission => 'edit_all_posts,publish_post', 
    689415                condition  => sub { 
     
    695421                label       => "Add Tags...", 
    696422                order       => 300, 
    697                 code        => \&add_tags_to_entries
     423                code        => "${pkg}Tag::add_tags_to_entries"
    698424                input       => 1, 
    699425                input_label => 'Tags to add to selected entries', 
     
    706432                label       => "Remove Tags...", 
    707433                order       => 400, 
    708                 code        => \&remove_tags_from_entries
     434                code        => "${pkg}Tag::remove_tags_from_entries"
    709435                input       => 1, 
    710436                input_label => 'Tags to remove from selected entries', 
     
    716442            'open_batch_editor' => { 
    717443                label     => "Batch Edit Entries", 
    718                 code      => \&open_batch_editor
     444                code      => "${pkg}Entry::open_batch_editor"
    719445                order     => 500, 
    720446                condition => sub { 
     
    730456                label      => "Publish Pages", 
    731457                order      => 100, 
    732                 code       => \&publish_entries
     458                code       => "${pkg}Entry::publish_entries"
    733459&n