<?php
/**
* This file implements the UI controller for additional tools.
*
* b2evolution - {@link http://b2evolution.net/}
* Released under GNU GPL License - {@link http://b2evolution.net/about/gnu-gpl-license}
* @copyright (c)2003-2020 by Francois Planque - {@link http://fplanque.com/}
*
* @package admin
* @author blueyed: Daniel HAHLER
*/
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
global $deferred_AdminToolActions;
// Check permission:
check_user_perm( 'admin', 'normal', true );
check_user_perm( 'options', 'view', true );
load_funcs( 'plugins/_plugin.funcs.php' );
load_funcs( 'tools/model/_maintenance.funcs.php' );
load_funcs( 'tools/model/_tool.funcs.php' );
load_funcs( 'tools/model/_system.funcs.php' );
//load_funcs( '_core/model/db/_upgrade.funcs.php' );
// load item class
load_class( 'items/model/_item.class.php', 'Item' );
if( check_user_perm( 'options', 'edit' ) &&
( $action != 'utf8check' && $action != 'utf8upgrade' ) &&
system_check_charset_update() )
{ // DB charset is required to update
$Messages->add( sprintf( TB_('WARNING: Your database and/or some of your tables have a different charset/collation than the expected. It is strongly recommended to upgrade your database charset by running the tool <a %s>Check/Convert/Normalize the charsets/collations used by the DB (UTF-8 / ASCII)</a>.'), 'href="'.$admin_url.'?ctrl=tools&action=utf8check&'.url_crumb( 'tools' ).'"' ) );
}
param( 'tab', 'string', '', true );
param( 'tab3', 'string', 'tools', true );
if( $tab3 == 'import' )
{ // Check permission for import pages:
check_user_perm( 'options', 'edit', true );
}
$tab_Plugin = NULL;
$tab_plugin_ID = false;
if( ! empty($tab) )
{ // We have requested a tab which is handled by a plugin:
if( preg_match( '~^plug_ID_(\d+)$~', $tab, $match ) )
{ // Instanciate the invoked plugin:
$tab_plugin_ID = $match[1];
$tab_Plugin = & $Plugins->get_by_ID( $match[1] );
if( ! $tab_Plugin )
{ // Plugin does not exist
$Messages->add( sprintf( TB_( 'The plugin with ID %d could not get instantiated.' ), $tab_plugin_ID ), 'error' );
$tab_plugin_ID = false;
$tab_Plugin = false;
$tab = '';
}
else
{
$plugin_params = array();
$Plugins->call_method_if_active( $tab_plugin_ID, 'AdminTabAction', $plugin_params );
}
}
else
{
$tab = '';
$Messages->add( 'Invalid sub-menu!' ); // Should need no translation, prevented by GUI
}
}
// Highlight the requested tab (if valid):
if( $tab_Plugin && method_exists( $tab_Plugin, 'adminUI_set_path' ) )
{
$tab_Plugin->adminUI_set_path( $AdminUI );
}
else
{
$AdminUI->set_path( 'options', 'misc', !empty( $tab ) ? $tab : $tab3 );
}
if( empty( $tab ) )
{ // "Main tab" actions:
if( param( 'action', 'string', '' ) )
{
// Check that this action request is not a CSRF hacked request:
$Session->assert_received_crumb( 'tools' );
// fp> TODO: have an option to only PRUNE files older than for example 30 days
check_user_perm('options', 'edit', true);
}
set_max_execution_time( 0 );
$Plugins->trigger_event( 'AdminToolAction' );
switch( $action )
{
case 'del_itemprecache':
// Clear pre-rendered item cache (DB)
$template_log_title = TB_('Clear pre-rendered item cache (DB)');
$template_action = $action;
break;
case 'del_commentprecache':
// Clear pre-rendered comment cache (DB)
$template_log_title = TB_('Clear pre-rendered comment cache (DB)');
$template_action = $action;
break;
case 'del_messageprecache':
// Clear pre-rendered message cache (DB)
$template_log_title = TB_('Clear pre-rendered message cache (DB)');
$template_action = $action;
break;
case 'del_pagecache':
// Delete the page cache /blogs/cache
$template_log_title = TB_('Clear full page caches (/_cache/* directories)');
$template_action = $action;
break;
case 'del_filecache':
// delete the thumbnail cahces .evocache
$template_log_title = TB_('Clear thumbnail caches (_evocache directories)');
$template_action = $action;
break;
case 'repair_cache':
// Repair cache
$template_log_title = TB_('Repair /_cache/* directory structure');
$template_action = $action;
break;
case 'optimize_tables':
// Optimize MyISAM & InnoDB tables
$template_log_title = TB_('OPTIMIZE database tables');
$template_action = $action;
break;
case 'check_tables':
// Check ALL database tables
$template_log_title = TB_('CHECK database tables');
$template_action = $action;
break;
case 'analyze_tables': // Analize ALL database tables
$template_log_title = TB_('ANALYZE database tables');
$template_action = $action;
break;
case 'del_broken_posts':
// Delete all broken posts that have no matching category
$template_action = $action;
break;
case 'del_broken_slugs':
// Find all broken slugs that have no matching target post
dbm_delete_broken_slugs();
break;
case 'delete_orphan_comments':
// delete orphan orphan comments with no matching Item
$template_log_title = TB_('Find and delete all orphan Comments (with no matching Item) - Disk & DB.');
$template_action = $action;
break;
case 'delete_orphan_comment_uploads':
// delete orphan comment upload, older than 24 hours
$template_log_title = TB_('Find and delete all orphan comment Uploads - Disk & DB.');
$template_action = $action;
break;
case 'delete_orphan_files':
// delete orphan File objects with no matching file on disk
$template_log_title = TB_('Find and delete all orphan File objects (with no matching file on disk) - DB only.');
$template_action = $action;
break;
case 'delete_orphan_file_roots':
// delete orphan file roots with no matching Blog or User entry in the database
$template_log_title = TB_('Find and delete all orphan file roots (with no matching Collection or User) and all of their content recursively - Disk & DB.');
$template_action = $action;
break;
case 'prune_hits_sessions':
// Prune old hits & sessions
$template_log_title = TB_('Prune old hits & sessions (includes OPTIMIZE) - DB only.');
$template_action = $action;
break;
case 'create_sample_collections':
// Create sample collections:
$num_collections = param( 'num_collections', 'integer', 0 );
$perm_management = param( 'perm_management', 'array:string' );
if( empty( $perm_management ) )
{ // At least one option must be selected:
$Messages->add( sprintf( TB_('Please selected at least one option of the setting "%s".'), TB_('Permission management') ), 'error' );
}
$allow_access = param( 'allow_access', 'array:string' );
if( empty( $allow_access ) )
{ // At least one option must be selected:
$Messages->add( sprintf( TB_('Please selected at least one option of the setting "%s".'), TB_('Allow access to') ), 'error' );
}
if( param_errors_detected() )
{ // If some param errors then stop a creating and display a form to correct:
$action = 'show_create_collections';
break;
}
// Execute a creating of collections inside template in order to see a process:
$template_action = 'create_sample_collections';
break;
case 'create_sample_comments':
$blog_ID = param( 'blog_ID', 'string', 0 );
$num_comments = param( 'num_comments', 'string', 0 );
$num_posts = param( 'num_posts', 'string', 0 );
if( ! ( param_check_number( 'blog_ID', TB_('Blog ID must be a number'), true ) &&
param_check_number( 'num_comments', TB_('Comments per post must be a number'), true ) &&
param_check_number( 'num_posts', TB_('"How many posts" field must be a number'), true ) ) )
{ // param errors
$action = 'show_create_comments';
break;
}
// check blog_ID
$BlogCache = & get_BlogCache();
$selected_Blog = $BlogCache->get_by_ID( $blog_ID, false, false );
if( $selected_Blog == NULL )
{
$Messages->add( TB_( 'Blog ID must be a valid Blog ID!' ), 'error' );
$action = 'show_create_comments';
break;
}
// Execute a creating of comments inside template in order to see a process
$template_action = 'create_sample_comments';
break;
case 'create_sample_posts':
$blog_ID = param( 'blog_ID', 'string', 0 );
$num_posts = param( 'num_posts', 'string', 0 );
if( ! ( param_check_number( 'blog_ID', TB_('Blog ID must be a number'), true ) &&
param_check_number( 'num_posts', TB_('"How many posts" field must be a number'), true ) ) )
{ // param errors
$action = 'show_create_posts';
break;
}
// check blog_ID
$BlogCache = & get_BlogCache();
$selected_Blog = $BlogCache->get_by_ID( $blog_ID, false, false );
if( $selected_Blog == NULL )
{
$Messages->add( TB_( 'Blog ID must be a valid Blog ID!' ), 'error' );
$action = 'show_create_posts';
break;
}
// Execute a creating of posts inside template in order to see a process
$template_action = 'create_sample_posts';
break;
case 'create_sample_revisions':
$blog_ID = param( 'blog_ID', 'string', 0 );
$min_revisions = param( 'min_revisions', 'string', 0 );
$max_revisions = param( 'max_revisions', 'string', 0 );
if( ! ( param_check_number( 'blog_ID', TB_('Blog ID must be a number'), true ) &&
param_check_number( 'min_revisions', TB_('Minimum number of revisions field must be a number'), true ) &&
param_check_number( 'max_revisions', TB_('Maximum number of revisions filed must be a number'), true ) ) )
{ // param errors
$action = 'show_create_revisions';
break;
}
// check blog_ID
$BlogCache = & get_BlogCache();
$selected_Blog = $BlogCache->get_by_ID( $blog_ID, false, false );
if( $selected_Blog == NULL )
{
$Messages->add( TB_('Blog ID must be a valid Blog ID!'), 'error' );
$action = 'show_create_revisions';
break;
}
// Execute a creating of revisions inside template in order to see the process
$template_action = 'create_sample_revisions';
break;
case 'create_sample_users':
$num_users = param( 'num_users', 'string', 0 );
param_check_number( 'num_users', TB_('"How many users" field must be a number'), true );
$user_groups = param( 'user_groups', 'array:integer' );
if( empty( $user_groups ) )
{ // At least one option must be selected:
$Messages->add( sprintf( TB_('Please select at least one option of the setting "%s".'), TB_('Create new users in') ), 'error' );
}
$advanced_user_perms = param( 'advanced_user_perms', 'array:string' );
if( empty( $advanced_user_perms ) )
{ // At least one option must be selected:
$Messages->add( sprintf( TB_('Please select at least one option of the setting "%s".'), TB_('Advanced user perms to grant on existing collections with advanced perms') ), 'error' );
}
if( param_errors_detected() )
{ // If some param errors then stop a creating and display a form to correct:
$action = 'show_create_users';
break;
}
// Execute a creating of users inside template in order to see a process
$template_action = 'create_sample_users';
break;
case 'recreate_itemslugs':
// Recreate all item slugs (change title-[0-9] canonical slugs to a slug generated from current title). Old slugs will still work, but redirect to the new one.
$template_log_title = TB_('Recreate all item Slugs (change title-[0-9] canonical slugs to a slug generated from current title). Old slugs will still work, but will redirect to the new ones - DB only.');
$template_action = $action;
break;
case 'recreate_autogenerated_excerpts':
// Recreating of autogenerated excerpts
$template_log_title = TB_('Recreate autogenerated excerpts - DB only.');
$template_action = $action;
break;
case 'convert_item_content_separators':
// Convert item content separators to new format
// Execute these actions inside template in order to see the process
$template_log_title = TB_('Convert item content separators to [teaserbreak] and [pagebreak] - DB only.');
$template_action = $action;
break;
case 'delete_item_versions':
param( 'confirmed', 'integer', 0 );
if( $confirmed )
{
$template_log_title = TB_('Remove all Item version - DB only.');
$template_action = $action;
}
else
{
$action = 'show_delete_item_versions';
}
break;
case 'resize_all_images':
param( 'confirmed', 'integer', 0 );
if( $confirmed )
{
$template_log_title = TB_('Resize all images in the media directory');
$template_action = $action;
}
else
{
$action = 'show_resize_all_images';
}
break;
case 'del_obsolete_tags':
$DB->query('
DELETE T_items__tag FROM T_items__tag
LEFT JOIN T_items__itemtag ON tag_ID = itag_tag_ID
WHERE itag_itm_ID IS NULL');
$Messages->add( sprintf(TB_('Removed %d obsolete tag entries.'), $DB->rows_affected), 'success' );
break;
case 'view_phpinfo':
// Display PHP info and exit
headers_content_mightcache('text/html');
phpinfo();
exit();
break;
case 'create_sample_hits':
$days = param( 'days', 'integer', 0 );
$min_interval = param( 'min_interval', 'integer', 0 );
$max_interval = param( 'max_interval', 'integer', 0 );
if( $days < 1 )
{
param_error( 'days', 'Please enter how many days of stats to generate' );
$action = 'show_create_hits';
break;
}
if( ( $min_interval > $max_interval ) || ( $min_interval < 0 ) || ( $max_interval <= 0 ) )
{
param_error( 'min_interval', 'Please enter correct interval values' );
param_error( 'max_interval', 'Please enter correct interval values' );
$action = 'show_create_hits';
break;
}
// Execute a creating of hits inside template in order to see a process
$template_action = 'create_sample_hits';
break;
case 'create_sample_basedomains':
// Create sample base domains:
$num_basedomains = param( 'num_basedomains', 'string', 0 );
if( ! param_check_number( 'num_basedomains', TB_('"How many base domains" field must be a number'), true ) )
{ // Stop action because of param error:
$action = 'show_create_basedomains';
break;
}
// Execute a creating of base domains inside template in order to see a process:
$template_action = 'create_sample_basedomains';
break;
case 'create_sample_messages':
$num_loops = param( 'num_loops', 'string', 0 );
$num_messages = param( 'num_messages', 'string', 0 );
$num_words = param( 'num_words', 'string', 0 );
$max_users = param( 'max_users', 'string', 0 );
if( ! ( param_check_number( 'num_loops', TB_('"How many loops" field must be a number'), true ) &&
param_check_number( 'num_messages', TB_('"How many messages in each conversation" field must be a number'), true ) &&
param_check_number( 'num_words', TB_('"How many words in each message" field must be a number'), true ) &&
param_check_number( 'max_users', TB_('"Max # of participants in a conversation" field must be a number'), true ) ) )
{ // param errors
$action = 'show_create_messages';
break;
}
// Execute a creating of messages inside template in order to see a process
$template_action = 'create_sample_messages';
break;
case 'create_sample_campaigns':
$num_campaigns = param( 'num_campaigns', 'string', 0 );
param_check_number( 'num_campaigns', TB_('"How many email campaigns" field must be a number'), true );
$campaign_lists = param( 'campaign_lists', 'array:integer' );
if( empty( $campaign_lists ) )
{ // At least one option must be selected:
$Messages->add_to_group( sprintf( TB_('Please select at least one option of the setting "%s".'), TB_('Create new email campaigns in') ), 'error', TB_('Validation errors:') );
}
if( param_errors_detected() )
{ // If some param errors then stop a creating and display a form to correct:
$action = 'show_create_campaigns';
break;
}
$send_campaign_emails = param( 'send_campaign_emails', 'integer', 0 );
// Execute a creating of users inside template in order to see a process
$template_action = 'create_sample_campaigns';
break;
case 'test_flush':
// Execute a testing of flush inside template in order to see a process
$template_action = 'test_flush';
$template_title = TB_('Log of test flush').get_manual_link( 'test-flush-tool' );
break;
case 'utf8check':
//$template_log_title = TB_('Check/Convert/Normalize the charsets/collations used by the DB (UTF-8 / ASCII)');
load_funcs('_core/model/db/_upgrade.funcs.php');
$template_log_title = TB_('Normalizing DB charsets...');
$template_action = $action;
break;
case 'utf8upgrade':
// Check/Upgrade DB to UTF-8
load_funcs('_core/model/db/_upgrade.funcs.php');
$template_log_title = TB_('Normalizing DB charsets...');
$template_action = $action;
break;
case 'update_tools':
// UPDATE general settings from tools:
// Check permission:
check_user_perm( 'options', 'edit', true );
// Lock system
if( check_user_perm( 'users', 'edit' ) )
{
$system_lock = param( 'system_lock', 'integer', 0 );
if( $Settings->get( 'system_lock' ) && ( ! $system_lock ) && ( ! $Messages->has_errors() ) && ( 1 == $Messages->count() ) )
{ // System lock was turned off and there was no error, remove the warning about the system lock
$Messages->clear();
}
$Settings->set( 'system_lock', $system_lock );
}
if( ! $Messages->has_errors() )
{
$Settings->dbupdate();
$Messages->add( TB_('Site settings updated.'), 'success' );
}
// Redirect so that a reload doesn't write to the DB twice:
header_redirect( '?ctrl=tools', 303 ); // Will EXIT
// We have EXITed already at this point!!
break;
}
}
$AdminUI->breadcrumbpath_init( false ); // fp> I'm playing with the idea of keeping the current blog in the path here...
$AdminUI->breadcrumbpath_add( TB_('System'), $admin_url.'?ctrl=system' );
$AdminUI->breadcrumbpath_add( TB_('Maintenance'), $admin_url.'?ctrl=tools' );
switch( $tab3 )
{
case 'import':
$AdminUI->breadcrumbpath_add( TB_('Import'), $admin_url.'?ctrl=tools&tab3=import' );
// Set an url for manual page:
$AdminUI->set_page_manual_link( 'import-tab' );
break;
case 'test':
$AdminUI->breadcrumbpath_add( TB_('Testing'), $admin_url.'?ctrl=tools&tab3=import' );
// Set an url for manual page:
$AdminUI->set_page_manual_link( 'testing-tools' );
break;
case 'tools':
default:
$AdminUI->breadcrumbpath_add( TB_('Tools'), $admin_url.'?ctrl=tools' );
// Set an url for manual page:
$AdminUI->set_page_manual_link( 'tools-tab' );
break;
}
// Display <html><head>...</head> section! (Note: should be done early if actions do not redirect)
$AdminUI->disp_html_head();
// Display title, menu, messages, etc. (Note: messages MUST be displayed AFTER the actions)
$AdminUI->disp_body_top();
// Begin payload block:
$AdminUI->disp_payload_begin();
if( empty( $tab ) )
{
switch( $action )
{
case 'find_broken_posts':
$AdminUI->disp_view( 'tools/views/_broken_posts.view.php' );
break;
case 'find_broken_slugs':
$AdminUI->disp_view( 'tools/views/_broken_slugs.view.php' );
break;
case 'show_create_collections':
$AdminUI->disp_view( 'tools/views/_create_collections.form.php' );
break;
case 'show_create_comments':
$AdminUI->disp_view( 'tools/views/_create_comments.form.php' );
break;
case 'show_create_posts':
$AdminUI->disp_view( 'tools/views/_create_posts.form.php' );
break;
case 'show_create_revisions':
$AdminUI->disp_view( 'tools/views/_create_revisions.form.php' );
break;
case 'show_create_users':
$AdminUI->disp_view( 'tools/views/_create_users.form.php' );
break;
case 'show_create_hits':
$AdminUI->disp_view( 'tools/views/_create_test_hit.form.php' );
break;
case 'show_create_basedomains':
$AdminUI->disp_view( 'tools/views/_create_basedomains.form.php' );
break;
case 'show_create_messages':
// Get count users
$SQL = new SQL( 'Get a count of all users' );
$SQL->SELECT( 'COUNT( user_ID )' );
$SQL->FROM( 'T_users' );
$users_count = $DB->get_var( $SQL );
$threads_count = $users_count * $users_count - $users_count + 1;
$AdminUI->disp_view( 'tools/views/_create_messages.form.php' );
break;
case 'show_create_campaigns':
$AdminUI->disp_view( 'tools/views/_create_campaigns.form.php' );
break;
case 'show_delete_item_versions':
$AdminUI->disp_view( 'tools/views/_delete_item_versions.form.php' );
$AdminUI->disp_view( 'tools/views/_misc_tools.view.php' );
break;
case 'show_resize_all_images':
$AdminUI->disp_view( 'tools/views/_image_resize.form.php' );
$AdminUI->disp_view( 'tools/views/_misc_tools.view.php' );
break;
case 'show_orphan_files_form':
$AdminUI->disp_view( 'tools/views/_tool_orphan_files.form.php' );
break;
default:
switch( $tab3 )
{
case 'import':
$AdminUI->disp_view( 'tools/views/_misc_import.view.php' );
break;
case 'test':
$AdminUI->disp_view( 'tools/views/_misc_test.view.php' );
break;
case 'tools':
default:
$AdminUI->disp_view( 'tools/views/_misc_tools.view.php' );
break;
}
break;
}
}
elseif( $tab_Plugin )
{ // Plugin tab
// Icons:
?>
<div class="right_icons">
<?php
echo $tab_Plugin->get_edit_settings_link()
.' '.$tab_Plugin->get_help_link('$help_url');
?>
</div>
<?php
$plugin_params = array();
$Plugins->call_method_if_active( $tab_plugin_ID, 'AdminTabPayload', $plugin_params );
}
// End payload block:
$AdminUI->disp_payload_end();
// Display body bottom, debug info and close </html>:
$AdminUI->disp_global_footer();
?>