aboutsummaryrefslogtreecommitdiffstats
path: root/phpBB/includes
diff options
context:
space:
mode:
Diffstat (limited to 'phpBB/includes')
-rw-r--r--phpBB/includes/acp/acp_bbcodes.php14
-rw-r--r--phpBB/includes/acp/acp_bots.php10
-rw-r--r--phpBB/includes/acp/acp_forums.php8
-rw-r--r--phpBB/includes/acp/acp_icons.php12
-rw-r--r--phpBB/includes/acp/acp_main.php47
-rw-r--r--phpBB/includes/acp/acp_modules.php11
-rw-r--r--phpBB/includes/acp/acp_permissions.php2
-rw-r--r--phpBB/includes/acp/acp_profile.php53
-rw-r--r--phpBB/includes/acp/acp_ranks.php16
-rw-r--r--phpBB/includes/acp/acp_styles.php3188
-rw-r--r--phpBB/includes/acp/acp_users.php4
-rw-r--r--phpBB/includes/acp/auth.php4
-rw-r--r--phpBB/includes/acp/info/acp_styles.php6
-rw-r--r--phpBB/includes/auth/auth.php (renamed from phpBB/includes/auth.php)2
-rw-r--r--phpBB/includes/bbcode.php13
-rw-r--r--phpBB/includes/db/dbal.php35
-rw-r--r--phpBB/includes/db/mysql.php70
-rw-r--r--phpBB/includes/db/mysqli.php70
-rw-r--r--phpBB/includes/event/data.php68
-rw-r--r--phpBB/includes/event/dispatcher.php42
-rw-r--r--phpBB/includes/event/extension_subscriber_loader.php46
-rw-r--r--phpBB/includes/extension/controller.php77
-rw-r--r--phpBB/includes/extension/controller_interface.php31
-rw-r--r--phpBB/includes/extension/finder.php4
-rw-r--r--phpBB/includes/extension/manager.php56
-rw-r--r--phpBB/includes/functions.php88
-rw-r--r--phpBB/includes/functions_admin.php10
-rw-r--r--phpBB/includes/functions_content.php20
-rw-r--r--phpBB/includes/functions_display.php1
-rw-r--r--phpBB/includes/functions_download.php2
-rw-r--r--phpBB/includes/functions_messenger.php126
-rw-r--r--phpBB/includes/functions_module.php26
-rw-r--r--phpBB/includes/functions_posting.php69
-rw-r--r--phpBB/includes/functions_privmsgs.php19
-rw-r--r--phpBB/includes/functions_profile_fields.php13
-rw-r--r--phpBB/includes/functions_user.php33
-rw-r--r--phpBB/includes/json_response.php41
-rw-r--r--phpBB/includes/mcp/mcp_main.php9
-rw-r--r--phpBB/includes/mcp/mcp_post.php6
-rw-r--r--phpBB/includes/mcp/mcp_queue.php31
-rw-r--r--phpBB/includes/mcp/mcp_reports.php9
-rw-r--r--phpBB/includes/mcp/mcp_topic.php11
-rw-r--r--phpBB/includes/mcp/mcp_warn.php4
-rw-r--r--phpBB/includes/request/type_cast_helper.php2
-rw-r--r--phpBB/includes/search/base.php2
-rw-r--r--phpBB/includes/search/fulltext_mysql.php8
-rw-r--r--phpBB/includes/search/fulltext_native.php15
-rw-r--r--phpBB/includes/session.php842
-rw-r--r--phpBB/includes/startup.php34
-rw-r--r--phpBB/includes/style/extension_path_provider.php125
-rw-r--r--phpBB/includes/style/path_provider.php74
-rw-r--r--phpBB/includes/style/path_provider_interface.php49
-rw-r--r--phpBB/includes/style/resource_locator.php (renamed from phpBB/includes/template/locator.php)69
-rw-r--r--phpBB/includes/style/style.php151
-rw-r--r--phpBB/includes/style/template.php (renamed from phpBB/includes/template/template.php)112
-rw-r--r--phpBB/includes/style/template_compile.php (renamed from phpBB/includes/template/compile.php)4
-rw-r--r--phpBB/includes/style/template_context.php (renamed from phpBB/includes/template/context.php)23
-rw-r--r--phpBB/includes/style/template_filter.php (renamed from phpBB/includes/template/filter.php)2
-rw-r--r--phpBB/includes/style/template_renderer.php (renamed from phpBB/includes/template/renderer.php)4
-rw-r--r--phpBB/includes/style/template_renderer_eval.php (renamed from phpBB/includes/template/renderer_eval.php)6
-rw-r--r--phpBB/includes/style/template_renderer_include.php (renamed from phpBB/includes/template/renderer_include.php)4
-rw-r--r--phpBB/includes/template/extension_path_provider.php130
-rw-r--r--phpBB/includes/template/path_provider.php102
-rw-r--r--phpBB/includes/template/path_provider_interface.php54
-rw-r--r--phpBB/includes/ucp/ucp_remind.php2
-rw-r--r--phpBB/includes/ucp/ucp_zebra.php22
-rw-r--r--phpBB/includes/user.php851
67 files changed, 3425 insertions, 3669 deletions
diff --git a/phpBB/includes/acp/acp_bbcodes.php b/phpBB/includes/acp/acp_bbcodes.php
index a3822a982a..e537d7a8b9 100644
--- a/phpBB/includes/acp/acp_bbcodes.php
+++ b/phpBB/includes/acp/acp_bbcodes.php
@@ -24,7 +24,7 @@ class acp_bbcodes
function main($id, $mode)
{
- global $db, $user, $auth, $template, $cache;
+ global $db, $user, $auth, $template, $cache, $request;
global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
$user->add_lang('acp/posting');
@@ -272,6 +272,18 @@ class acp_bbcodes
$db->sql_query('DELETE FROM ' . BBCODES_TABLE . " WHERE bbcode_id = $bbcode_id");
$cache->destroy('sql', BBCODES_TABLE);
add_log('admin', 'LOG_BBCODE_DELETE', $row['bbcode_tag']);
+
+ if ($request->is_ajax())
+ {
+ $json_response = new phpbb_json_response;
+ $json_response->send(array(
+ 'MESSAGE_TITLE' => $user->lang['INFORMATION'],
+ 'MESSAGE_TEXT' => $user->lang['BBCODE_DELETED'],
+ 'REFRESH_DATA' => array(
+ 'time' => 3
+ )
+ ));
+ }
}
else
{
diff --git a/phpBB/includes/acp/acp_bots.php b/phpBB/includes/acp/acp_bots.php
index f080b3c9fb..b9dd6664f4 100644
--- a/phpBB/includes/acp/acp_bots.php
+++ b/phpBB/includes/acp/acp_bots.php
@@ -24,7 +24,7 @@ class acp_bots
function main($id, $mode)
{
- global $config, $db, $user, $auth, $template, $cache;
+ global $config, $db, $user, $auth, $template, $cache, $request;
global $phpbb_root_path, $phpbb_admin_path, $phpEx, $table_prefix;
$action = request_var('action', '');
@@ -352,6 +352,14 @@ class acp_bots
break;
}
+
+ if ($request->is_ajax() && ($action == 'activate' || $action == 'deactivate'))
+ {
+ $json_response = new phpbb_json_response;
+ $json_response->send(array(
+ 'text' => $user->lang['BOT_' . (($action == 'activate') ? 'DE' : '') . 'ACTIVATE'],
+ ));
+ }
$s_options = '';
$_options = array('activate' => 'BOT_ACTIVATE', 'deactivate' => 'BOT_DEACTIVATE', 'delete' => 'DELETE');
diff --git a/phpBB/includes/acp/acp_forums.php b/phpBB/includes/acp/acp_forums.php
index fad22fc285..3a3b2021eb 100644
--- a/phpBB/includes/acp/acp_forums.php
+++ b/phpBB/includes/acp/acp_forums.php
@@ -25,7 +25,7 @@ class acp_forums
function main($id, $mode)
{
- global $db, $user, $auth, $template, $cache;
+ global $db, $user, $auth, $template, $cache, $request;
global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx;
$user->add_lang('acp/forums');
@@ -255,6 +255,12 @@ class acp_forums
add_log('admin', 'LOG_FORUM_' . strtoupper($action), $row['forum_name'], $move_forum_name);
$cache->destroy('sql', FORUMS_TABLE);
}
+
+ if ($request->is_ajax())
+ {
+ $json_response = new phpbb_json_response;
+ $json_response->send(array('success' => ($move_forum_name !== false)));
+ }
break;
diff --git a/phpBB/includes/acp/acp_icons.php b/phpBB/includes/acp/acp_icons.php
index 49a092f16b..bfe17c5007 100644
--- a/phpBB/includes/acp/acp_icons.php
+++ b/phpBB/includes/acp/acp_icons.php
@@ -782,6 +782,18 @@ class acp_icons
$cache->destroy('_icons');
$cache->destroy('sql', $table);
+
+ if ($request->is_ajax())
+ {
+ $json_response = new phpbb_json_response;
+ $json_response->send(array(
+ 'MESSAGE_TITLE' => $user->lang['INFORMATION'],
+ 'MESSAGE_TEXT' => $notice,
+ 'REFRESH_DATA' => array(
+ 'time' => 3
+ )
+ ));
+ }
}
else
{
diff --git a/phpBB/includes/acp/acp_main.php b/phpBB/includes/acp/acp_main.php
index b30c294ce2..144b225766 100644
--- a/phpBB/includes/acp/acp_main.php
+++ b/phpBB/includes/acp/acp_main.php
@@ -24,7 +24,7 @@ class acp_main
function main($id, $mode)
{
- global $config, $db, $user, $auth, $template;
+ global $config, $db, $user, $auth, $template, $request;
global $phpbb_root_path, $phpbb_admin_path, $phpEx;
// Show restore permissions notice
@@ -129,6 +129,11 @@ class acp_main
set_config('record_online_users', 1, true);
set_config('record_online_date', time(), true);
add_log('admin', 'LOG_RESET_ONLINE');
+
+ if ($request->is_ajax())
+ {
+ trigger_error('RESET_ONLINE_SUCCESS');
+ }
break;
case 'stats':
@@ -179,6 +184,11 @@ class acp_main
update_last_username();
add_log('admin', 'LOG_RESYNC_STATS');
+
+ if ($request->is_ajax())
+ {
+ trigger_error('RESYNC_STATS_SUCCESS');
+ }
break;
case 'user':
@@ -241,7 +251,11 @@ class acp_main
}
add_log('admin', 'LOG_RESYNC_POSTCOUNTS');
-
+
+ if ($request->is_ajax())
+ {
+ trigger_error('RESYNC_POSTCOUNTS_SUCCESS');
+ }
break;
case 'date':
@@ -252,6 +266,11 @@ class acp_main
set_config('board_startdate', time() - 1);
add_log('admin', 'LOG_RESET_DATE');
+
+ if ($request->is_ajax())
+ {
+ trigger_error('RESET_DATE_SUCCESS');
+ }
break;
case 'db_track':
@@ -327,14 +346,14 @@ class acp_main
}
add_log('admin', 'LOG_RESYNC_POST_MARKING');
- break;
-
- case 'purge_cache':
- if ((int) $user->data['user_type'] !== USER_FOUNDER)
+
+ if ($request->is_ajax())
{
- trigger_error($user->lang['NO_AUTH_OPERATION'] . adm_back_link($this->u_action), E_USER_WARNING);
+ trigger_error('RESYNC_POST_MARKING_SUCCESS');
}
+ break;
+ case 'purge_cache':
global $cache;
$cache->purge();
@@ -343,6 +362,11 @@ class acp_main
cache_moderators();
add_log('admin', 'LOG_PURGE_CACHE');
+
+ if ($request->is_ajax())
+ {
+ trigger_error('PURGE_CACHE_SUCCESS');
+ }
break;
case 'purge_sessions':
@@ -389,6 +413,11 @@ class acp_main
$db->sql_query($sql);
add_log('admin', 'LOG_PURGE_SESSIONS');
+
+ if ($request->is_ajax())
+ {
+ trigger_error('PURGE_SESSIONS_SUCCESS');
+ }
break;
}
}
@@ -397,11 +426,11 @@ class acp_main
// Version check
$user->add_lang('install');
- if ($auth->acl_get('a_server') && version_compare(PHP_VERSION, '5.2.0', '<'))
+ if ($auth->acl_get('a_server') && version_compare(PHP_VERSION, '5.3.2', '<'))
{
$template->assign_vars(array(
'S_PHP_VERSION_OLD' => true,
- 'L_PHP_VERSION_OLD' => sprintf($user->lang['PHP_VERSION_OLD'], '<a href="http://www.phpbb.com/community/viewtopic.php?f=14&amp;t=1958605">', '</a>'),
+ 'L_PHP_VERSION_OLD' => sprintf($user->lang['PHP_VERSION_OLD'], '<a href="http://www.phpbb.com/community/viewtopic.php?f=14&amp;t=2152375">', '</a>'),
));
}
diff --git a/phpBB/includes/acp/acp_modules.php b/phpBB/includes/acp/acp_modules.php
index 9d87bbbfbb..8528dc91c4 100644
--- a/phpBB/includes/acp/acp_modules.php
+++ b/phpBB/includes/acp/acp_modules.php
@@ -36,7 +36,7 @@ class acp_modules
function main($id, $mode)
{
- global $db, $user, $auth, $template, $module;
+ global $db, $user, $auth, $template, $module, $request;
global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx;
// Set a global define for modules we might include (the author is able to prevent execution of code by checking this constant)
@@ -373,6 +373,15 @@ class acp_modules
// Default management page
if (sizeof($errors))
{
+ if ($request->is_ajax())
+ {
+ $json_response = new phpbb_json_response;
+ $json_response->send(array(
+ 'MESSAGE_TITLE' => $user->lang('ERROR'),
+ 'MESSAGE_TEXT' => implode('<br />', $errors),
+ ));
+ }
+
$template->assign_vars(array(
'S_ERROR' => true,
'ERROR_MSG' => implode('<br />', $errors))
diff --git a/phpBB/includes/acp/acp_permissions.php b/phpBB/includes/acp/acp_permissions.php
index 150b67b8f7..d728744c04 100644
--- a/phpBB/includes/acp/acp_permissions.php
+++ b/phpBB/includes/acp/acp_permissions.php
@@ -1105,7 +1105,7 @@ class acp_permissions
{
if ($user_id != $user->data['user_id'])
{
- $auth2 = new auth();
+ $auth2 = new phpbb_auth();
$auth2->acl($userdata);
$auth_setting = $auth2->acl_get($permission);
}
diff --git a/phpBB/includes/acp/acp_profile.php b/phpBB/includes/acp/acp_profile.php
index 60d5def4d1..3ffffd3047 100644
--- a/phpBB/includes/acp/acp_profile.php
+++ b/phpBB/includes/acp/acp_profile.php
@@ -242,6 +242,15 @@ class acp_profile
$db->sql_freeresult($result);
add_log('admin', 'LOG_PROFILE_FIELD_ACTIVATE', $field_ident);
+
+ if ($request->is_ajax())
+ {
+ $json_response = new phpbb_json_response();
+ $json_response->send(array(
+ 'text' => $user->lang('DEACTIVATE'),
+ ));
+ }
+
trigger_error($user->lang['PROFILE_FIELD_ACTIVATED'] . adm_back_link($this->u_action));
break;
@@ -266,7 +275,16 @@ class acp_profile
$field_ident = (string) $db->sql_fetchfield('field_ident');
$db->sql_freeresult($result);
+ if ($request->is_ajax())
+ {
+ $json_response = new phpbb_json_response();
+ $json_response->send(array(
+ 'text' => $user->lang('ACTIVATE'),
+ ));
+ }
+
add_log('admin', 'LOG_PROFILE_FIELD_DEACTIVATE', $field_ident);
+
trigger_error($user->lang['PROFILE_FIELD_DEACTIVATED'] . adm_back_link($this->u_action));
break;
@@ -508,11 +526,34 @@ class acp_profile
}
}
}
- /* else if ($field_type == FIELD_BOOL && $key == 'field_default_value')
+ else if ($field_type == FIELD_BOOL && $key == 'field_default_value')
{
- // Get the number of options if this key is 'field_maxlen'
- $var = request_var('field_default_value', 0);
- }*/
+ // 'field_length' == 1 defines radio buttons. Possible values are 1 or 2 only.
+ // 'field_length' == 2 defines checkbox. Possible values are 0 or 1 only.
+ // If we switch the type on step 2, we have to adjust field value.
+ // 1 is a common value for the checkbox and radio buttons.
+
+ // Adjust unchecked checkbox value.
+ // If we return or save settings from 2nd/3rd page
+ // and the checkbox is unchecked, set the value to 0.
+ if (isset($_REQUEST['step']) && !isset($_REQUEST[$key]))
+ {
+ $var = 0;
+ }
+
+ // If we switch to the checkbox type but former radio buttons value was 2,
+ // which is not the case for the checkbox, set it to 0 (unchecked).
+ if ($cp->vars['field_length'] == 2 && $var == 2)
+ {
+ $var = 0;
+ }
+ // If we switch to the radio buttons but the former checkbox value was 0,
+ // which is not the case for the radio buttons, set it to 0.
+ else if ($cp->vars['field_length'] == 1 && $var == 0)
+ {
+ $var = 2;
+ }
+ }
else if ($field_type == FIELD_INT && $key == 'field_default_value')
{
// Permit an empty string
@@ -680,6 +721,10 @@ class acp_profile
{
$_new_key_ary[$key] = utf8_normalize_nfc(request_var($key, array(array('')), true));
}
+ else if ($field_type == FIELD_BOOL && $key == 'field_default_value')
+ {
+ $_new_key_ary[$key] = request_var($key, $cp->vars[$key]);
+ }
else
{
if (!isset($_REQUEST[$key]))
diff --git a/phpBB/includes/acp/acp_ranks.php b/phpBB/includes/acp/acp_ranks.php
index 97cfd35750..d9ed5b17f1 100644
--- a/phpBB/includes/acp/acp_ranks.php
+++ b/phpBB/includes/acp/acp_ranks.php
@@ -24,7 +24,7 @@ class acp_ranks
function main($id, $mode)
{
- global $db, $user, $auth, $template, $cache;
+ global $db, $user, $auth, $template, $cache, $request;
global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
$user->add_lang('acp/posting');
@@ -51,7 +51,7 @@ class acp_ranks
}
$rank_title = utf8_normalize_nfc(request_var('title', '', true));
$special_rank = request_var('special_rank', 0);
- $min_posts = ($special_rank) ? 0 : request_var('min_posts', 0);
+ $min_posts = ($special_rank) ? 0 : max(0, request_var('min_posts', 0));
$rank_image = request_var('rank_image', '');
// The rank image has to be a jpg, gif or png
@@ -122,6 +122,18 @@ class acp_ranks
$cache->destroy('_ranks');
add_log('admin', 'LOG_RANK_REMOVED', $rank_title);
+
+ if ($request->is_ajax())
+ {
+ $json_response = new phpbb_json_response;
+ $json_response->send(array(
+ 'MESSAGE_TITLE' => $user->lang['INFORMATION'],
+ 'MESSAGE_TEXT' => $user->lang['RANK_REMOVED'],
+ 'REFRESH_DATA' => array(
+ 'time' => 3
+ )
+ ));
+ }
}
else
{
diff --git a/phpBB/includes/acp/acp_styles.php b/phpBB/includes/acp/acp_styles.php
index c8fe748c02..2772fb2217 100644
--- a/phpBB/includes/acp/acp_styles.php
+++ b/phpBB/includes/acp/acp_styles.php
@@ -21,2589 +21,1287 @@ if (!defined('IN_PHPBB'))
class acp_styles
{
var $u_action;
-
- var $style_cfg;
- var $template_cfg;
- var $theme_cfg;
+ var $u_base_action;
+ var $s_hidden_fields;
+ var $mode;
+ var $styles_path;
+ var $styles_path_absolute = 'styles';
function main($id, $mode)
{
- global $db, $user, $auth, $template, $cache;
- global $config, $phpbb_root_path, $phpbb_admin_path, $phpEx;
+ global $user, $phpbb_admin_path, $phpbb_root_path, $phpEx, $template, $request;
- // Hardcoded template bitfield to add for new templates
- $bitfield = new bitfield();
- $bitfield->set(0);
- $bitfield->set(1);
- $bitfield->set(2);
- $bitfield->set(3);
- $bitfield->set(4);
- $bitfield->set(8);
- $bitfield->set(9);
- $bitfield->set(11);
- $bitfield->set(12);
- $this->template_bitfield = $bitfield->get_base64();
- unset($bitfield);
+ $this->styles_path = $phpbb_root_path . $this->styles_path_absolute . '/';
+
+ $this->u_base_action = append_sid("{$phpbb_admin_path}index.$phpEx", "i={$id}");
+ $this->s_hidden_fields = array(
+ 'mode' => $mode,
+ );
$user->add_lang('acp/styles');
$this->tpl_name = 'acp_styles';
$this->page_title = 'ACP_CAT_STYLES';
+ $this->mode = $mode;
- $action = request_var('action', '');
- $action = (isset($_POST['add'])) ? 'add' : $action;
- $style_id = request_var('id', 0);
-
- // Fill the configuration variables
- $this->style_cfg = $this->template_cfg = $this->theme_cfg = '
-#
-# phpBB {MODE} configuration file
-#
-# @package phpBB3
-# @copyright (c) 2005 phpBB Group
-# @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
-#
-#
-# At the left is the name, please do not change this
-# At the right the value is entered
-# For on/off options the valid values are on, off, 1, 0, true and false
-#
-# Values get trimmed, if you want to add a space in front or at the end of
-# the value, then enclose the value with single or double quotes.
-# Single and double quotes do not need to be escaped.
-#
-#
-
-# General Information about this {MODE}
-name = {NAME}
-copyright = {COPYRIGHT}
-version = {VERSION}
-';
-
- $this->template_cfg .= '
-# Some configuration options
-
-#
-# You can use this function to inherit templates from another template.
-# The template of the given name has to be installed.
-# Templates cannot inherit from inheriting templates.
-#';
-
- // Execute overall actions
- switch ($action)
+ $action = $request->variable('action', '');
+ $post_actions = array('install', 'activate', 'deactivate', 'uninstall');
+ foreach ($post_actions as $key)
{
- case 'delete':
- if ($style_id)
- {
- $this->remove($mode, $style_id);
- return;
- }
- break;
-
- case 'export':
- if ($style_id)
- {
- $this->export($mode, $style_id);
- return;
- }
- break;
+ if (isset($_POST[$key]))
+ {
+ $action = $key;
+ }
+ }
+ if ($action != '')
+ {
+ $this->s_hidden_fields['action'] = $action;
+ }
+ $template->assign_vars(array(
+ 'U_ACTION' => $this->u_base_action,
+ 'S_HIDDEN_FIELDS' => build_hidden_fields($this->s_hidden_fields)
+ )
+ );
+
+ // Execute actions
+ switch ($action)
+ {
case 'install':
- $this->install($mode);
+ $this->action_install();
return;
- break;
-
- case 'add':
- $this->add($mode);
+ case 'uninstall':
+ $this->action_uninstall();
+ return;
+ case 'activate':
+ $this->action_activate();
+ return;
+ case 'deactivate':
+ $this->action_deactivate();
return;
- break;
-
case 'details':
- if ($style_id)
- {
- $this->details($mode, $style_id);
- return;
- }
- break;
-
- case 'edit':
- if ($style_id)
- {
- switch ($mode)
- {
- case 'template':
- return $this->edit_template($style_id);
- case 'theme':
- return $this->edit_theme($style_id);
- }
- }
- break;
-
- case 'cache':
- if ($style_id)
- {
- switch ($mode)
- {
- case 'template':
- return $this->template_cache($style_id);
- }
- }
- break;
+ $this->action_details();
+ return;
+ default:
+ $this->frontend();
}
-
- switch ($mode)
+ }
+
+ /**
+ * Main page
+ */
+ function frontend()
+ {
+ // Check mode
+ switch ($this->mode)
{
case 'style':
-
- switch ($action)
- {
- case 'activate':
- case 'deactivate':
-
- if ($style_id == $config['default_style'])
- {
- trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING);
- }
-
- if (($action == 'deactivate' && confirm_box(true)) || $action == 'activate')
- {
- $sql = 'UPDATE ' . STYLES_TABLE . '
- SET style_active = ' . (($action == 'activate') ? 1 : 0) . '
- WHERE style_id = ' . $style_id;
- $db->sql_query($sql);
-
- // Set style to default for any member using deactivated style
- if ($action == 'deactivate')
- {
- $sql = 'UPDATE ' . USERS_TABLE . '
- SET user_style = ' . $config['default_style'] . "
- WHERE user_style = $style_id";
- $db->sql_query($sql);
-
- $sql = 'UPDATE ' . FORUMS_TABLE . '
- SET forum_style = 0
- WHERE forum_style = ' . $style_id;
- $db->sql_query($sql);
- }
- }
- else if ($action == 'deactivate')
- {
- $s_hidden_fields = array(
- 'i' => $id,
- 'mode' => $mode,
- 'action' => $action,
- 'style_id' => $style_id,
- );
- confirm_box(false, $user->lang['CONFIRM_OPERATION'], build_hidden_fields($s_hidden_fields));
- }
- break;
- }
-
- $this->frontend('style', array('details'), array('export', 'delete'));
- break;
-
- case 'template':
-
- switch ($action)
- {
- // Clear cache
- case 'refresh':
-
- $sql = 'SELECT *
- FROM ' . STYLES_TEMPLATE_TABLE . "
- WHERE template_id = $style_id";
- $result = $db->sql_query($sql);
- $template_row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$template_row)
- {
- trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
- }
-
- if (confirm_box(true))
- {
- $this->clear_template_cache($template_row);
-
- trigger_error($user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action));
- }
- else
- {
- confirm_box(false, $user->lang['CONFIRM_TEMPLATE_CLEAR_CACHE'], build_hidden_fields(array(
- 'i' => $id,
- 'mode' => $mode,
- 'action' => $action,
- 'id' => $style_id
- )));
- }
-
- break;
- }
-
- $this->frontend('template', array('edit', 'cache', 'details'), array('refresh', 'export', 'delete'));
- break;
-
- case 'theme':
- $this->frontend('theme', array('edit', 'details'), array('export', 'delete'));
- break;
+ $this->welcome_message('ACP_STYLES', 'ACP_STYLES_EXPLAIN');
+ $this->show_installed();
+ return;
+ case 'install':
+ $this->welcome_message('INSTALL_STYLES', 'INSTALL_STYLES_EXPLAIN');
+ $this->show_available();
+ return;
+ case 'cache':
+ $this->action_cache();
+ return;
}
+ global $user;
+ trigger_error($user->lang['NO_MODE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
-
+
/**
- * Build Frontend with supplied options
+ * Purge cache
*/
- function frontend($mode, $options, $actions)
+ function action_cache()
{
- global $user, $template, $db, $config, $phpbb_root_path, $phpEx;
-
- $sql_from = '';
- $sql_sort = 'LOWER(' . $mode . '_name)';
- $style_count = array();
-
- switch ($mode)
- {
- case 'style':
- $sql_from = STYLES_TABLE;
- $sql_sort = 'style_active DESC, ' . $sql_sort;
+ global $cache, $auth, $user;
+
+ $cache->purge();
- $sql = 'SELECT user_style, COUNT(user_style) AS style_count
- FROM ' . USERS_TABLE . '
- GROUP BY user_style';
- $result = $db->sql_query($sql);
+ // Clear permissions
+ $auth->acl_clear_prefetch();
+ cache_moderators();
- while ($row = $db->sql_fetchrow($result))
+ add_log('admin', 'LOG_PURGE_CACHE');
+
+ trigger_error($user->lang['PURGED_CACHE'] . adm_back_link($this->u_base_action), E_USER_NOTICE);
+ }
+
+ /**
+ * Install style(s)
+ */
+ function action_install()
+ {
+ global $user;
+
+ // Get list of styles to install
+ $dirs = $this->request_vars('dir', '', true);
+
+ // Get list of styles that can be installed
+ $styles = $this->find_available(false);
+
+ // Install each style
+ $messages = array();
+ $installed_names = array();
+ $installed_dirs = array();
+ $last_installed = false;
+ foreach ($dirs as $dir)
+ {
+ $found = false;
+ foreach ($styles as &$style)
+ {
+ // Check if:
+ // 1. Directory matches directory we are looking for
+ // 2. Style is not installed yet
+ // 3. Style with same name or directory hasn't been installed already within this function
+ if ($style['style_path'] == $dir && empty($style['_installed']) && !in_array($style['style_path'], $installed_dirs) && !in_array($style['style_name'], $installed_names))
{
- $style_count[$row['user_style']] = $row['style_count'];
+ // Install style
+ $style['style_active'] = 1;
+ $style['style_id'] = $this->install_style($style);
+ $style['_installed'] = true;
+ $found = true;
+ $last_installed = $style['style_id'];
+ $installed_names[] = $style['style_name'];
+ $installed_dirs[] = $style['style_path'];
+ $messages[] = sprintf($user->lang['STYLE_INSTALLED'], htmlspecialchars($style['style_name']));
}
- $db->sql_freeresult($result);
-
- break;
-
- case 'template':
- $sql_from = STYLES_TEMPLATE_TABLE;
- break;
-
- case 'theme':
- $sql_from = STYLES_THEME_TABLE;
- break;
-
- default:
- trigger_error($user->lang['NO_MODE'] . adm_back_link($this->u_action), E_USER_WARNING);
- }
-
- $l_prefix = strtoupper($mode);
-
- $this->page_title = 'ACP_' . $l_prefix . 'S';
-
- $template->assign_vars(array(
- 'S_FRONTEND' => true,
- 'S_STYLE' => ($mode == 'style') ? true : false,
-
- 'L_TITLE' => $user->lang[$this->page_title],
- 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
- 'L_NAME' => $user->lang[$l_prefix . '_NAME'],
- 'L_INSTALLED' => $user->lang['INSTALLED_' . $l_prefix],
- 'L_UNINSTALLED' => $user->lang['UNINSTALLED_' . $l_prefix],
- 'L_NO_UNINSTALLED' => $user->lang['NO_UNINSTALLED_' . $l_prefix],
- 'L_CREATE' => $user->lang['CREATE_' . $l_prefix],
-
- 'U_ACTION' => $this->u_action,
- )
- );
-
- $sql = "SELECT *
- FROM $sql_from
- ORDER BY $sql_sort ASC";
- $result = $db->sql_query($sql);
-
- $installed = array();
-
- $basis_options = '<option class="sep" value="">' . $user->lang['OPTIONAL_BASIS'] . '</option>';
- while ($row = $db->sql_fetchrow($result))
- {
- $installed[] = $row[$mode . '_name'];
- $basis_options .= '<option value="' . $row[$mode . '_id'] . '">' . $row[$mode . '_name'] . '</option>';
-
- $stylevis = ($mode == 'style' && !$row['style_active']) ? 'activate' : 'deactivate';
-
- $s_options = array();
- foreach ($options as $option)
- {
- $s_options[] = '<a href="' . $this->u_action . "&amp;action=$option&amp;id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>';
}
-
- $s_actions = array();
- foreach ($actions as $option)
+ if (!$found)
{
- $s_actions[] = '<a href="' . $this->u_action . "&amp;action=$option&amp;id=" . $row[$mode . '_id'] . '">' . $user->lang[strtoupper($option)] . '</a>';
+ $messages[] = sprintf($user->lang['STYLE_NOT_INSTALLED'], htmlspecialchars($dir));
}
-
- $template->assign_block_vars('installed', array(
- 'S_DEFAULT_STYLE' => ($mode == 'style' && $row['style_id'] == $config['default_style']) ? true : false,
- 'U_EDIT' => $this->u_action . '&amp;action=' . (($mode == 'style') ? 'details' : 'edit') . '&amp;id=' . $row[$mode . '_id'],
- 'U_STYLE_ACT_DEACT' => $this->u_action . '&amp;action=' . $stylevis . '&amp;id=' . $row[$mode . '_id'],
- 'L_STYLE_ACT_DEACT' => $user->lang['STYLE_' . strtoupper($stylevis)],
- 'S_OPTIONS' => implode(' | ', $s_options),
- 'S_ACTIONS' => implode(' | ', $s_actions),
- 'U_PREVIEW' => ($mode == 'style') ? append_sid("{$phpbb_root_path}index.$phpEx", "$mode=" . $row[$mode . '_id']) : '',
-
- 'NAME' => $row[$mode . '_name'],
- 'STYLE_COUNT' => ($mode == 'style' && isset($style_count[$row['style_id']])) ? $style_count[$row['style_id']] : 0,
-
- 'S_INACTIVE' => ($mode == 'style' && !$row['style_active']) ? true : false,
- )
- );
}
- $db->sql_freeresult($result);
-
- // Grab uninstalled items
- $new_ary = $cfg = array();
-
- $dp = @opendir("{$phpbb_root_path}styles");
-
- if ($dp)
+
+ // Show message
+ if (!count($messages))
{
- while (($file = readdir($dp)) !== false)
- {
- if ($file[0] == '.' || !is_dir($phpbb_root_path . 'styles/' . $file))
- {
- continue;
- }
-
- $subpath = ($mode != 'style') ? "$mode/" : '';
- if (file_exists("{$phpbb_root_path}styles/$file/$subpath$mode.cfg"))
- {
- if ($cfg = file("{$phpbb_root_path}styles/$file/$subpath$mode.cfg"))
- {
- $items = parse_cfg_file('', $cfg);
- $name = (isset($items['name'])) ? trim($items['name']) : false;
-
- if ($name && !in_array($name, $installed))
- {
- $new_ary[] = array(
- 'path' => $file,
- 'name' => $name,
- 'copyright' => $items['copyright'],
- );
- }
- }
- }
- }
- closedir($dp);
+ trigger_error($user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);
}
-
- unset($installed);
-
- if (sizeof($new_ary))
- {
- foreach ($new_ary as $cfg)
- {
- $template->assign_block_vars('uninstalled', array(
- 'NAME' => $cfg['name'],
- 'COPYRIGHT' => $cfg['copyright'],
- 'U_INSTALL' => $this->u_action . '&amp;action=install&amp;path=' . urlencode($cfg['path']))
- );
- }
+ $message = implode('<br />', $messages);
+ $message .= '<br /><br />' . sprintf($user->lang['STYLE_INSTALLED_RETURN_STYLES'], $this->u_base_action . '&amp;mode=style');
+ $message .= '<br /><br />' . sprintf($user->lang['STYLE_INSTALLED_RETURN_UNINSTALLED'], $this->u_base_action . '&amp;mode=install');
+ trigger_error($message, E_USER_NOTICE);
+ }
+
+ /**
+ * Confirm styles removal
+ */
+ function action_uninstall()
+ {
+ global $user, $config, $template, $request;
+
+ // Get list of styles to uninstall
+ $ids = $this->request_vars('id', 0, true);
+
+ // Check if confirmation box was submitted
+ if (confirm_box(true))
+ {
+ // Uninstall
+ $this->action_uninstall_confirmed($ids, $request->variable('confirm_delete_files', false));
+ return;
}
- unset($new_ary);
-
- $template->assign_vars(array(
- 'S_BASIS_OPTIONS' => $basis_options)
- );
-
+
+ // Confirm box
+ $s_hidden = build_hidden_fields(array(
+ 'action' => 'uninstall',
+ 'ids' => $ids
+ ));
+ $template->assign_var('S_CONFIRM_DELETE', true);
+ confirm_box(false, $user->lang['CONFIRM_UNINSTALL_STYLES'], $s_hidden, 'acp_styles.html');
+
+ // Canceled - show styles list
+ $this->frontend();
}
/**
- * Provides a template editor which allows saving changes to template files on the filesystem or in the database.
+ * Uninstall styles(s)
*
- * @param int $template_id specifies which template set is being edited
+ * @param array $ids List of style IDs
+ * @param bool $delete_files If true, script will attempt to remove files for selected styles
*/
- function edit_template($template_id)
+ function action_uninstall_confirmed($ids, $delete_files)
{
- global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode;
+ global $db, $user, $cache, $config;
- if (defined('PHPBB_DISABLE_ACP_EDITOR'))
- {
- trigger_error($user->lang['EDITOR_DISABLED'] . adm_back_link($this->u_action));
- }
-
- $this->page_title = 'EDIT_TEMPLATE';
-
- $filelist = $filelist_cats = array();
-
- $template_data = utf8_normalize_nfc(request_var('template_data', '', true));
- $template_data = htmlspecialchars_decode($template_data);
- $template_file = utf8_normalize_nfc(request_var('template_file', '', true));
- $text_rows = max(5, min(999, request_var('text_rows', 20)));
- $save_changes = (isset($_POST['save'])) ? true : false;
-
- // make sure template_file path doesn't go upwards
- $template_file = preg_replace('#\.{2,}#', '.', $template_file);
-
- // Retrieve some information about the template
- $sql = 'SELECT template_path, template_name
- FROM ' . STYLES_TEMPLATE_TABLE . "
- WHERE template_id = $template_id";
- $result = $db->sql_query($sql);
- $template_info = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$template_info)
- {
- trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
- }
+ $default = $config['default_style'];
+ $uninstalled = array();
+ $messages = array();
- // Get the filesystem location of the current file
- $template_path = "{$phpbb_root_path}styles/{$template_info['template_path']}/template";
- $file = "$template_path/$template_file";
-
- if ($template_file)
+ // Check styles list
+ foreach ($ids as $id)
{
- $l_not_writable = sprintf($user->lang['TEMPLATE_FILE_NOT_WRITABLE'], htmlspecialchars($template_file)) . adm_back_link($this->u_action);
-
- if ($safe_mode)
- {
- trigger_error($l_not_writable, E_USER_WARNING);
- }
-
- if (file_exists($file) && is_file($file) && is_readable($file))
+ if (!$id)
{
- if (!phpbb_is_writable($file))
- {
- trigger_error($l_not_writable, E_USER_WARNING);
- }
+ trigger_error($user->lang['INVALID_STYLE_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- else
+ if ($id == $default)
{
- trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
+ trigger_error($user->lang['UNINSTALL_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING);
}
+ $uninstalled[$id] = false;
}
- if ($save_changes && !check_form_key('acp_styles'))
- {
- trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
- }
- else if (!$save_changes)
- {
- add_form_key('acp_styles');
- }
+ // Order by reversed style_id, so parent styles would be removed after child styles
+ // This way parent and child styles can be removed in same function call
+ $sql = 'SELECT *
+ FROM ' . STYLES_TABLE . '
+ WHERE style_id IN (' . implode(', ', $ids) . ')
+ ORDER BY style_id DESC';
+ $result = $db->sql_query($sql);
+
+ $rows = $db->sql_fetchrowset($result);
+ $db->sql_freeresult($result);
- // save changes to the template if the user submitted any
- if ($save_changes && $template_file)
+ // Uinstall each style
+ $uninstalled = array();
+ foreach ($rows as $style)
{
- // Try to write the file
- if (!($fp = @fopen($file, 'wb')))
+ $result = $this->uninstall_style($style, $delete_files);
+
+ if (is_string($result))
{
- // File exists and is writeable, but still not able to be written to
- trigger_error($l_not_writable, E_USER_WARNING);
+ $messages[] = $result;
+ continue;
}
- fwrite($fp, $template_data);
- fclose($fp);
-
- // destroy the cached version of the template (filename without extension)
- $this->clear_template_cache($template_info, array(substr($template_file, 0, -5)));
-
- $cache->destroy('sql', STYLES_TABLE);
+ $messages[] = sprintf($user->lang['STYLE_UNINSTALLED'], $style['style_name']);
+ $uninstalled[] = $style['style_name'];
- add_log('admin', 'LOG_TEMPLATE_EDIT', $template_info['template_name'], $template_file);
- trigger_error($user->lang['TEMPLATE_FILE_UPDATED'] . adm_back_link($this->u_action . "&amp;action=edit&amp;id=$template_id&amp;text_rows=$text_rows&amp;template_file=$template_file"));
- }
-
- // Generate a category array containing template filenames
-
- $filelist = filelist($template_path, '', 'html');
- $filelist[''] = array_diff($filelist[''], array('bbcode.html'));
-
- if ($template_file)
- {
- $template_data = file_get_contents($file);
-
- if (!$template_data)
+ // Attempt to delete files
+ if ($delete_files)
{
- trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
+ $messages[] = sprintf($user->lang[$this->delete_style_files($style['style_path']) ? 'DELETE_STYLE_FILES_SUCCESS' : 'DELETE_STYLE_FILES_FAILED'], $style['style_name']);
}
}
- if (empty($filelist['']))
+ if (empty($messages))
{
- trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
+ // Nothing to uninstall?
+ trigger_error($user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);
}
- // Now create the categories
- $filelist_cats[''] = array();
- foreach ($filelist as $pathfile => $file_ary)
+ // Log action
+ if (count($uninstalled))
{
- // Use the directory name as category name
- if (!empty($pathfile))
- {
- $filelist_cats[$pathfile] = array();
- foreach ($file_ary as $file)
- {
- $filelist_cats[$pathfile][$pathfile . $file] = $file;
- }
- }
- // or if it's in the main category use the word before the first underscore to group files
- else
- {
- $cats = array();
- foreach ($file_ary as $file)
- {
- $cats[] = substr($file, 0, strpos($file, '_'));
- $filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file;
- }
-
- $cats = array_values(array_unique($cats));
-
- // we don't need any single element categories so put them into the misc '' category
- for ($i = 0, $n = sizeof($cats); $i < $n; $i++)
- {
- if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '')
- {
- $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]);
- unset($filelist_cats[$cats[$i]]);
- }
- }
- unset($cats);
- }
+ add_log('admin', 'LOG_STYLE_DELETE', implode(', ', $uninstalled));
}
- unset($filelist);
-
- // Generate list of categorised template files
- $tpl_options = '';
- ksort($filelist_cats);
- foreach ($filelist_cats as $category => $tpl_ary)
- {
- ksort($tpl_ary);
-
- if (!empty($category))
- {
- $tpl_options .= '<option class="sep" value="">' . $category . '</option>';
- }
- foreach ($tpl_ary as $filename => $file)
- {
- $selected = ($template_file == $filename) ? ' selected="selected"' : '';
- $tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>';
- }
- }
+ // Clear cache
+ $cache->purge();
- $template->assign_vars(array(
- 'S_EDIT_TEMPLATE' => true,
- 'S_HIDDEN_FIELDS' => build_hidden_fields(array('template_file' => $template_file)),
- 'S_TEMPLATES' => $tpl_options,
-
- 'U_ACTION' => $this->u_action . "&amp;action=edit&amp;id=$template_id&amp;text_rows=$text_rows",
- 'U_BACK' => $this->u_action,
-
- 'L_EDIT' => $user->lang['EDIT_TEMPLATE'],
- 'L_EDIT_EXPLAIN' => $user->lang['EDIT_TEMPLATE_EXPLAIN'],
- 'L_EDITOR' => $user->lang['TEMPLATE_EDITOR'],
- 'L_EDITOR_HEIGHT' => $user->lang['TEMPLATE_EDITOR_HEIGHT'],
- 'L_FILE' => $user->lang['TEMPLATE_FILE'],
- 'L_SELECT' => $user->lang['SELECT_TEMPLATE'],
- 'L_SELECTED' => $user->lang['SELECTED_TEMPLATE'],
- 'L_SELECTED_FILE' => $user->lang['SELECTED_TEMPLATE_FILE'],
-
- 'SELECTED_TEMPLATE' => $template_info['template_name'],
- 'TEMPLATE_FILE' => $template_file,
- 'TEMPLATE_DATA' => utf8_htmlspecialchars($template_data),
- 'TEXT_ROWS' => $text_rows)
- );
+ // Show message
+ trigger_error(implode('<br />', $messages) . adm_back_link($this->u_action), E_USER_NOTICE);
}
/**
- * Allows the admin to view cached versions of template files and clear single template cache files
- *
- * @param int $template_id specifies which template's cache is shown
+ * Activate styles
*/
- function template_cache($template_id)
+ function action_activate()
{
- global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template;
-
- $source = str_replace('/', '.', request_var('source', ''));
- $file_ary = array_diff(request_var('delete', array('')), array(''));
- $submit = isset($_POST['submit']) ? true : false;
-
- $sql = 'SELECT *
- FROM ' . STYLES_TEMPLATE_TABLE . "
- WHERE template_id = $template_id";
- $result = $db->sql_query($sql);
- $template_row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
+ global $user, $config, $cache, $db;
+
+ // Get list of styles to activate
+ $ids = $this->request_vars('id', 0, true);
+
+ // Activate styles
+ $sql = 'UPDATE ' . STYLES_TABLE . '
+ SET style_active = 1
+ WHERE style_id IN (' . implode(', ', $ids) . ')';
+ $db->sql_query($sql);
- if (!$template_row)
- {
- trigger_error($user->lang['NO_TEMPLATE'] . adm_back_link($this->u_action), E_USER_WARNING);
- }
+ // Purge cache
+ $cache->destroy('sql', STYLES_TABLE);
+
+ // Show styles list
+ $this->frontend();
+ }
- // User wants to delete one or more files ...
- if ($submit && $file_ary)
- {
- $this->clear_template_cache($template_row, $file_ary);
- trigger_error($user->lang['TEMPLATE_CACHE_CLEARED'] . adm_back_link($this->u_action . "&amp;action=cache&amp;id=$template_id"));
- }
+ /**
+ * Deactivate styles
+ */
+ function action_deactivate()
+ {
+ global $user, $config, $cache, $db;
- $cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']);
+ // Get list of styles to deactivate
+ $ids = $this->request_vars('id', 0, true);
- // Someone wants to see the cached source ... so we'll highlight it,
- // add line numbers and indent it appropriately. This could be nasty
- // on larger source files ...
- if ($source && file_exists("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx"))
+ // Check for default style
+ foreach ($ids as $id)
{
- adm_page_header($user->lang['TEMPLATE_CACHE']);
-
- $template->set_filenames(array(
- 'body' => 'viewsource.html')
- );
-
- $template->assign_vars(array(
- 'FILENAME' => str_replace('.', '/', $source) . '.html')
- );
-
- $code = str_replace(array("\r\n", "\r"), array("\n", "\n"), file_get_contents("{$phpbb_root_path}cache/{$cache_prefix}_$source.html.$phpEx"));
-
- $conf = array('highlight.bg', 'highlight.comment', 'highlight.default', 'highlight.html', 'highlight.keyword', 'highlight.string');
- foreach ($conf as $ini_var)
+ if ($id == $config['default_style'])
{
- @ini_set($ini_var, str_replace('highlight.', 'syntax', $ini_var));
+ trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($this->u_action), E_USER_WARNING);
}
-
- $marker = 'MARKER' . time();
- $code = highlight_string(str_replace("\n", $marker, $code), true);
- $code = str_replace($marker, "\n", $code);
- $str_from = array('<span style="color: ', '<font color="syntax', '</font>', '<code>', '</code>','[', ']', '.', ':');
- $str_to = array('<span class="', '<span class="syntax', '</span>', '', '', '&#91;', '&#93;', '&#46;', '&#58;');
-
- $code = str_replace($str_from, $str_to, $code);
- $code = preg_replace('#^(<span class="[a-z_]+">)\n?(.*?)\n?(</span>)$#ism', '$1$2$3', $code);
- $code = substr($code, strlen('<span class="syntaxhtml">'));
- $code = substr($code, 0, -1 * strlen('</ span>'));
- $code = explode("\n", $code);
-
- foreach ($code as $key => $line)
- {
- $template->assign_block_vars('source', array(
- 'LINENUM' => $key + 1,
- 'LINE' => preg_replace('#([^ ;])&nbsp;([^ &])#', '$1 $2', $line))
- );
- unset($code[$key]);
- }
-
- adm_page_footer();
}
- // Get a list of cached template files and then retrieve additional information about them
- $file_ary = $this->template_cache_filelist($template_row['template_path']);
-
- foreach ($file_ary as $file)
- {
- $file = str_replace('/', '.', $file);
-
- // perform some dirty guessing to get the path right.
- // We assume that three dots in a row were '../'
- $tpl_file = str_replace('.', '/', $file);
- $tpl_file = str_replace('///', '../', $tpl_file);
-
- $filename = "{$cache_prefix}_$file.html.$phpEx";
-
- if (!file_exists("{$phpbb_root_path}cache/$filename"))
- {
- continue;
- }
-
- $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_path']}/template/$tpl_file.html";
- $inherited = false;
-
- if (isset($template_row['template_inherits_id']) && $template_row['template_inherits_id'] && !file_exists($file_tpl))
- {
- $file_tpl = "{$phpbb_root_path}styles/{$template_row['template_inherit_path']}/template/$tpl_file.html";
- $inherited = true;
- }
-
- $template->assign_block_vars('file', array(
- 'U_VIEWSOURCE' => $this->u_action . "&amp;action=cache&amp;id=$template_id&amp;source=$file",
+ // Reset default style for users who use selected styles
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_style = 0
+ WHERE user_style IN (' . implode(', ', $ids) . ')';
+ $db->sql_query($sql);
- 'CACHED' => $user->format_date(filemtime("{$phpbb_root_path}cache/$filename")),
- 'FILENAME' => $file,
- 'FILENAME_PATH' => $file_tpl,
- 'FILESIZE' => get_formatted_filesize(filesize("{$phpbb_root_path}cache/$filename")),
- 'MODIFIED' => $user->format_date(filemtime($file_tpl)),
- ));
- }
+ // Deactivate styles
+ $sql = 'UPDATE ' . STYLES_TABLE . '
+ SET style_active = 0
+ WHERE style_id IN (' . implode(', ', $ids) . ')';
+ $db->sql_query($sql);
- $template->assign_vars(array(
- 'S_CACHE' => true,
- 'S_TEMPLATE' => true,
+ // Purge cache
+ $cache->destroy('sql', STYLES_TABLE);
- 'U_ACTION' => $this->u_action . "&amp;action=cache&amp;id=$template_id",
- 'U_BACK' => $this->u_action)
- );
+ // Show styles list
+ $this->frontend();
}
-
+
/**
- * Provides a css editor and a basic easier to use stylesheet editing tool for less experienced (or lazy) users
- *
- * @param int $theme_id specifies which theme is being edited
+ * Show style details
*/
- function edit_theme($theme_id)
+ function action_details()
{
- global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template, $safe_mode;
-
- $this->page_title = 'EDIT_THEME';
-
- $filelist = $filelist_cats = array();
-
- $theme_data = utf8_normalize_nfc(request_var('template_data', '', true));
- $theme_data = htmlspecialchars_decode($theme_data);
- $theme_file = utf8_normalize_nfc(request_var('template_file', '', true));
- $text_rows = max(5, min(999, request_var('text_rows', 20)));
- $save_changes = (isset($_POST['save'])) ? true : false;
-
- // make sure theme_file path doesn't go upwards
- $theme_file = str_replace('..', '.', $theme_file);
-
- // Retrieve some information about the theme
- $sql = 'SELECT theme_path, theme_name
- FROM ' . STYLES_THEME_TABLE . "
- WHERE theme_id = $theme_id";
- $result = $db->sql_query($sql);
-
- if (!($theme_info = $db->sql_fetchrow($result)))
- {
- trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
- }
- $db->sql_freeresult($result);
-
- // Get the filesystem location of the current file
- $theme_path = "{$phpbb_root_path}styles/{$theme_info['theme_path']}/theme";
- $file = "$theme_path/$theme_file";
-
- if ($theme_file)
+ global $user, $config, $db, $request, $template, $cache;
+
+ $id = $request->variable('id', 0);
+ if (!$id)
{
- $l_not_writable = sprintf($user->lang['THEME_FILE_NOT_WRITABLE'], htmlspecialchars($theme_file)) . adm_back_link($this->u_action);
-
- if ($safe_mode)
- {
- trigger_error($l_not_writable, E_USER_WARNING);
- }
-
- if (file_exists($file) && is_file($file) && is_readable($file))
- {
- if (!phpbb_is_writable($file))
- {
- trigger_error($l_not_writable, E_USER_WARNING);
- }
- }
- else
- {
- trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
- }
+ trigger_error($user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);
}
-
- // save changes to the theme if the user submitted any
- if ($save_changes && $theme_file)
+
+ // Get all styles
+ $styles = $this->get_styles();
+ usort($styles, 'acp_styles::sort_styles');
+
+ // Find current style
+ $style = false;
+ foreach ($styles as $row)
{
- $message = $user->lang['THEME_UPDATED'];
-
- if (!($fp = @fopen($file, 'wb')))
+ if ($row['style_id'] == $id)
{
- trigger_error($l_not_writable, E_USER_WARNING);
+ $style = $row;
+ break;
}
- fwrite($fp, $theme_data);
- fclose($fp);
-
- $cache->destroy('sql', STYLES_THEME_TABLE);
- add_log('admin', 'LOG_THEME_EDIT_FILE', $theme_info['theme_name'], $theme_file);
-
- trigger_error($message . adm_back_link($this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;template_file=$theme_file&amp;text_rows=$text_rows"));
}
- // Generate a category array containing theme filenames
- $filelist = filelist($theme_path, '', 'css');
-
- if ($theme_file)
+ if ($style === false)
{
- $theme_data = file_get_contents($file);
-
- if (!$theme_data)
- {
- trigger_error($user->lang['NO_THEME'] . adm_back_link($this->u_action), E_USER_WARNING);
- }
+ trigger_error($user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);
}
-
- // Now create the categories
- $filelist_cats[''] = array();
- foreach ($filelist as $pathfile => $file_ary)
+
+ // Find all available parent styles
+ $list = $this->find_possible_parents($styles, $id);
+
+ // Change data
+ if ($request->variable('update', false))
{
- // Use the directory name as category name
- if (!empty($pathfile))
+ $update = array(
+ 'style_name' => trim($request->variable('style_name', $style['style_name'])),
+ 'style_parent_id' => $request->variable('style_parent', (int) $style['style_parent_id']),
+ 'style_active' => $request->variable('style_active', (int) $style['style_active']),
+ );
+ $update_action = $this->u_action . '&amp;action=details&amp;id=' . $id;
+
+ // Check style name
+ if ($update['style_name'] != $style['style_name'])
{
- $filelist_cats[$pathfile] = array();
- foreach ($file_ary as $file)
+ if (!strlen($update['style_name']))
+ {
+ trigger_error($user->lang['STYLE_ERR_STYLE_NAME'] . adm_back_link($update_action), E_USER_WARNING);
+ }
+ foreach ($styles as $row)
{
- $filelist_cats[$pathfile][$pathfile . $file] = $file;
+ if ($row['style_name'] == $update['style_name'])
+ {
+ trigger_error($user->lang['STYLE_ERR_NAME_EXIST'] . adm_back_link($update_action), E_USER_WARNING);
+ }
}
}
- // or if it's in the main category use the word before the first underscore to group files
else
{
- $cats = array();
- foreach ($file_ary as $file)
- {
- $cats[] = substr($file, 0, strpos($file, '_'));
- $filelist_cats[substr($file, 0, strpos($file, '_'))][$file] = $file;
- }
-
- $cats = array_values(array_unique($cats));
-
- // we don't need any single element categories so put them into the misc '' category
- for ($i = 0, $n = sizeof($cats); $i < $n; $i++)
+ unset($update['style_name']);
+ }
+
+ // Check parent style id
+ if ($update['style_parent_id'] != $style['style_parent_id'])
+ {
+ if ($update['style_parent_id'] != 0)
{
- if (sizeof($filelist_cats[$cats[$i]]) == 1 && $cats[$i] !== '')
+ $found = false;
+ foreach ($list as $row)
+ {
+ if ($row['style_id'] == $update['style_parent_id'])
+ {
+ $found = true;
+ $update['style_parent_tree'] = ($row['style_parent_tree'] != '' ? $row['style_parent_tree'] . '/' : '') . $row['style_path'];
+ break;
+ }
+ }
+ if (!$found)
{
- $filelist_cats[''][key($filelist_cats[$cats[$i]])] = current($filelist_cats[$cats[$i]]);
- unset($filelist_cats[$cats[$i]]);
+ trigger_error($user->lang['STYLE_ERR_INVALID_PARENT'] . adm_back_link($update_action), E_USER_WARNING);
}
}
- unset($cats);
+ else
+ {
+ $update['style_parent_tree'] = '';
+ }
}
- }
- unset($filelist);
-
- // Generate list of categorised theme files
- $tpl_options = '';
- ksort($filelist_cats);
- foreach ($filelist_cats as $category => $tpl_ary)
- {
- ksort($tpl_ary);
-
- if (!empty($category))
+ else
{
- $tpl_options .= '<option class="sep" value="">' . $category . '</option>';
+ unset($update['style_parent_id']);
}
-
- foreach ($tpl_ary as $filename => $file)
+
+ // Check style_active
+ if ($update['style_active'] != $style['style_active'])
{
- $selected = ($theme_file == $filename) ? ' selected="selected"' : '';
- $tpl_options .= '<option value="' . $filename . '"' . $selected . '>' . $file . '</option>';
+ if (!$update['style_active'] && $config['default_style'] == $style['style_id'])
+ {
+ trigger_error($user->lang['DEACTIVATE_DEFAULT'] . adm_back_link($update_action), E_USER_WARNING);
+ }
}
- }
-
- $template->assign_vars(array(
- 'S_EDIT_THEME' => true,
- 'S_HIDDEN_FIELDS' => build_hidden_fields(array('template_file' => $theme_file)),
- 'S_TEMPLATES' => $tpl_options,
-
- 'U_ACTION' => $this->u_action . "&amp;action=edit&amp;id=$theme_id&amp;text_rows=$text_rows",
- 'U_BACK' => $this->u_action,
-
- 'L_EDIT' => $user->lang['EDIT_THEME'],
- 'L_EDIT_EXPLAIN' => $user->lang['EDIT_THEME_EXPLAIN'],
- 'L_EDITOR' => $user->lang['THEME_EDITOR'],
- 'L_EDITOR_HEIGHT' => $user->lang['THEME_EDITOR_HEIGHT'],
- 'L_FILE' => $user->lang['THEME_FILE'],
- 'L_SELECT' => $user->lang['SELECT_THEME'],
- 'L_SELECTED' => $user->lang['SELECTED_THEME'],
- 'L_SELECTED_FILE' => $user->lang['SELECTED_THEME_FILE'],
-
- 'SELECTED_TEMPLATE' => $theme_info['theme_name'],
- 'TEMPLATE_FILE' => $theme_file,
- 'TEMPLATE_DATA' => utf8_htmlspecialchars($theme_data),
- 'TEXT_ROWS' => $text_rows,
- ));
- }
-
- /**
- * Remove style/template/theme
- */
- function remove($mode, $style_id)
- {
- global $db, $template, $user, $phpbb_root_path, $cache, $config;
-
- $new_id = request_var('new_id', 0);
- $update = (isset($_POST['update'])) ? true : false;
- $sql_where = '';
-
- switch ($mode)
- {
- case 'style':
- $sql_from = STYLES_TABLE;
- $sql_select = 'style_id, style_name, template_id, theme_id';
- $sql_where = 'AND style_active = 1';
- break;
-
- case 'template':
- $sql_from = STYLES_TEMPLATE_TABLE;
- $sql_select = 'template_id, template_name, template_path';
- break;
-
- case 'theme':
- $sql_from = STYLES_THEME_TABLE;
- $sql_select = 'theme_id, theme_name, theme_path';
- break;
- }
-
- if ($mode === 'template' && ($conflicts = $this->check_inheritance($mode, $style_id)))
- {
- $l_type = strtoupper($mode);
- $msg = $user->lang[$l_type . '_DELETE_DEPENDENT'];
- foreach ($conflicts as $id => $values)
+ else
{
- $msg .= '<br />' . $values['template_name'];
+ unset($update['style_active']);
}
-
- trigger_error($msg . adm_back_link($this->u_action), E_USER_WARNING);
- }
-
- $l_prefix = strtoupper($mode);
-
- $sql = "SELECT $sql_select
- FROM $sql_from
- WHERE {$mode}_id = $style_id";
- $result = $db->sql_query($sql);
- $style_row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$style_row)
- {
- trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
- }
-
- $s_only_component = $this->display_component_options($mode, $style_row[$mode . '_id'], $style_row);
-
- if ($s_only_component)
- {
- trigger_error($user->lang['ONLY_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
- }
-
- if ($update)
- {
- if ($mode == 'style')
+
+ // Update data
+ if (count($update))
{
- $sql = "DELETE FROM $sql_from
- WHERE {$mode}_id = $style_id";
- $db->sql_query($sql);
-
- $sql = 'UPDATE ' . USERS_TABLE . "
- SET user_style = $new_id
- WHERE user_style = $style_id";
- $db->sql_query($sql);
-
- $sql = 'UPDATE ' . FORUMS_TABLE . "
- SET forum_style = $new_id
- WHERE forum_style = $style_id";
+ $sql = 'UPDATE ' . STYLES_TABLE . '
+ SET ' . $db->sql_build_array('UPDATE', $update) . "
+ WHERE style_id = $id";
$db->sql_query($sql);
-
- if ($style_id == $config['default_style'])
- {
- set_config('default_style', $new_id);
- }
-
- // Remove the components
- $components = array('template', 'theme');
- foreach ($components as $component)
+
+ $style = array_merge($style, $update);
+
+ if (isset($update['style_parent_id']))
{
- $new_id = request_var('new_' . $component . '_id', 0);
- $component_id = $style_row[$component . '_id'];
- $this->remove_component($component, $component_id, $new_id, $style_id);
+ // Update styles tree
+ $styles = $this->get_styles();
+ if ($this->update_styles_tree(&$styles, $style))
+ {
+ // Something was changed in styles tree, purge all cache
+ $cache->purge();
+ }
}
+ add_log('admin', 'LOG_STYLE_EDIT_DETAILS', $style['style_name']);
}
- else
+
+ // Update default style
+ $default = $request->variable('style_default', 0);
+ if ($default)
{
- $this->remove_component($mode, $style_id, $new_id);
+ if (!$style['style_active'])
+ {
+ trigger_error($user->lang['STYLE_DEFAULT_CHANGE_INACTIVE'] . adm_back_link($update_action), E_USER_WARNING);
+ }
+ set_config('default_style', $id);
+ $cache->purge();
}
-
- $cache->destroy('sql', STYLES_TABLE);
-
- add_log('admin', 'LOG_' . $l_prefix . '_DELETE', $style_row[$mode . '_name']);
- $message = ($mode != 'style') ? $l_prefix . '_DELETED_FS' : $l_prefix . '_DELETED';
- trigger_error($user->lang[$message] . adm_back_link($this->u_action));
- }
-
- $this->page_title = 'DELETE_' . $l_prefix;
-
- $template->assign_vars(array(
- 'S_DELETE' => true,
-
- 'L_TITLE' => $user->lang[$this->page_title],
- 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
- 'L_NAME' => $user->lang[$l_prefix . '_NAME'],
- 'L_REPLACE' => $user->lang['REPLACE_' . $l_prefix],
- 'L_REPLACE_EXPLAIN' => $user->lang['REPLACE_' . $l_prefix . '_EXPLAIN'],
-
- 'U_ACTION' => $this->u_action . "&amp;action=delete&amp;id=$style_id",
- 'U_BACK' => $this->u_action,
-
- 'NAME' => $style_row[$mode . '_name'],
- )
- );
-
- if ($mode == 'style')
- {
- $template->assign_vars(array(
- 'S_DELETE_STYLE' => true,
- ));
- }
- }
-
- /**
- * Remove template/theme entry from the database
- */
- function remove_component($component, $component_id, $new_id, $style_id = false)
- {
- global $db;
-
- if (($new_id == 0) || ($component === 'template' && ($conflicts = $this->check_inheritance($component, $component_id))))
- {
- // We can not delete the template, as the user wants to keep the component or an other template is inheriting from this one.
- return;
- }
-
- $component_in_use = array();
- if ($component != 'style')
- {
- $component_in_use = $this->component_in_use($component, $component_id, $style_id);
- }
-
- if (($new_id == -1) && !empty($component_in_use))
- {
- // We can not delete the component, as it is still in use
+
+ // Show styles list
+ $this->frontend();
return;
}
-
- switch ($component)
+
+ // Show parent styles
+ foreach ($list as $row)
{
- case 'template':
- $sql_from = STYLES_TEMPLATE_TABLE;
- break;
-
- case 'theme':
- $sql_from = STYLES_THEME_TABLE;
- break;
+ $template->assign_block_vars('parent_styles', array(
+ 'STYLE_ID' => $row['style_id'],
+ 'STYLE_NAME' => htmlspecialchars($row['style_name']),
+ 'LEVEL' => $row['level'],
+ 'SPACER' => str_repeat('&nbsp; ', $row['level']),
+ )
+ );
}
-
- $sql = "DELETE FROM $sql_from
- WHERE {$component}_id = $component_id";
- $db->sql_query($sql);
-
- $sql = 'UPDATE ' . STYLES_TABLE . "
- SET {$component}_id = $new_id
- WHERE {$component}_id = $component_id";
- $db->sql_query($sql);
+
+ // Show style details
+ $template->assign_vars(array(
+ 'S_STYLE_DETAILS' => true,
+ 'STYLE_ID' => $style['style_id'],
+ 'STYLE_NAME' => htmlspecialchars($style['style_name']),
+ 'STYLE_PATH' => htmlspecialchars($style['style_path']),
+ 'STYLE_COPYRIGHT' => strip_tags($style['style_copyright']),
+ 'STYLE_PARENT' => $style['style_parent_id'],
+ 'S_STYLE_ACTIVE' => $style['style_active'],
+ 'S_STYLE_DEFAULT' => ($style['style_id'] == $config['default_style'])
+ )
+ );
}
/**
- * Display the options which can be used to replace a style/template/theme
- *
- * @return boolean Returns true if the component is the only component and can not be deleted.
+ * List installed styles
*/
- function display_component_options($component, $component_id, $style_row = false, $style_id = false)
+ function show_installed()
{
- global $db, $template, $user;
+ global $user, $template;
- $is_only_component = true;
- $component_in_use = array();
- if ($component != 'style')
- {
- $component_in_use = $this->component_in_use($component, $component_id, $style_id);
- }
+ // Get all installed styles
+ $styles = $this->get_styles();
- $sql_where = '';
- switch ($component)
+ if (!count($styles))
{
- case 'style':
- $sql_from = STYLES_TABLE;
- $sql_where = 'WHERE style_active = 1';
- break;
-
- case 'template':
- $sql_from = STYLES_TEMPLATE_TABLE;
- $sql_where = 'WHERE template_inherits_id <> ' . $component_id;
- break;
-
- case 'theme':
- $sql_from = STYLES_THEME_TABLE;
- break;
+ trigger_error($user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);
}
+
+ usort($styles, 'acp_styles::sort_styles');
- $s_options = '';
- if (($component != 'style') && empty($component_in_use))
- {
- // If it is not in use, there must be another component
- $is_only_component = false;
-
- $sql = "SELECT {$component}_id, {$component}_name
- FROM $sql_from
- WHERE {$component}_id = {$component_id}";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- $s_options .= '<option value="-1" selected="selected">' . $user->lang['DELETE_' . strtoupper($component)] . '</option>';
- $s_options .= '<option value="0">' . sprintf($user->lang['KEEP_' . strtoupper($component)], $row[$component . '_name']) . '</option>';
- }
- else
+ // Get users
+ $users = $this->get_users();
+
+ // Add users counter to rows
+ foreach ($styles as &$style)
{
- $sql = "SELECT {$component}_id, {$component}_name
- FROM $sql_from
- $sql_where
- ORDER BY {$component}_name ASC";
- $result = $db->sql_query($sql);
-
- $s_keep_option = $s_options = '';
- while ($row = $db->sql_fetchrow($result))
- {
- if ($row[$component . '_id'] != $component_id)
- {
- $is_only_component = false;
- $s_options .= '<option value="' . $row[$component . '_id'] . '">' . sprintf($user->lang['REPLACE_WITH_OPTION'], $row[$component . '_name']) . '</option>';
- }
- else if ($component != 'style')
- {
- $s_keep_option = '<option value="0" selected="selected">' . sprintf($user->lang['KEEP_' . strtoupper($component)], $row[$component . '_name']) . '</option>';
- }
- }
- $db->sql_freeresult($result);
- $s_options = $s_keep_option . $s_options;
+ $style['_users'] = isset($users[$style['style_id']]) ? $users[$style['style_id']] : 0;
}
+
+ // Set up styles list variables
+ // Addons should increase this number and update template variable
+ $this->styles_list_cols = 4;
+ $template->assign_var('STYLES_LIST_COLS', $this->styles_list_cols);
- if (!$style_row)
- {
- $template->assign_var('S_REPLACE_' . strtoupper($component) . '_OPTIONS', $s_options);
- }
- else
+ // Show styles list
+ $this->show_styles_list(&$styles, 0, 0);
+
+ // Show styles with invalid inherits_id
+ foreach ($styles as $style)
{
- $template->assign_var('S_REPLACE_OPTIONS', $s_options);
- if ($component == 'style')
+ if (empty($style['_shown']))
{
- $components = array('template', 'theme');
- foreach ($components as $component)
- {
- $this->display_component_options($component, $style_row[$component . '_id'], false, $component_id, true);
- }
+ $style['_note'] = sprintf($user->lang['REQUIRES_STYLE'], htmlspecialchars($style['style_parent_tree']));
+ $this->list_style($style, 0);
}
}
- return $is_only_component;
- }
-
- /**
- * Check whether the component is still used by another style or component
- */
- function component_in_use($component, $component_id, $style_id = false)
- {
- global $db;
-
- $component_in_use = array();
+ // Add buttons
+ $template->assign_block_vars('extra_actions', array(
+ 'ACTION_NAME' => 'activate',
+ 'L_ACTION' => $user->lang['STYLE_ACTIVATE'],
+ )
+ );
- if ($style_id)
- {
- $sql = 'SELECT style_id, style_name
- FROM ' . STYLES_TABLE . "
- WHERE {$component}_id = {$component_id}
- AND style_id <> {$style_id}
- ORDER BY style_name ASC";
- }
- else
- {
- $sql = 'SELECT style_id, style_name
- FROM ' . STYLES_TABLE . "
- WHERE {$component}_id = {$component_id}
- ORDER BY style_name ASC";
- }
- $result = $db->sql_query($sql);
- while ($row = $db->sql_fetchrow($result))
- {
- $component_in_use[] = $row['style_name'];
- }
- $db->sql_freeresult($result);
+ $template->assign_block_vars('extra_actions', array(
+ 'ACTION_NAME' => 'deactivate',
+ 'L_ACTION' => $user->lang['STYLE_DEACTIVATE'],
+ )
+ );
- if ($component === 'template' && ($conflicts = $this->check_inheritance($component, $component_id)))
+ if (isset($this->style_counters) && $this->style_counters['total'] > 1)
{
- foreach ($conflicts as $temp_id => $conflict_data)
- {
- $component_in_use[] = $conflict_data['template_name'];
- }
+ $template->assign_block_vars('extra_actions', array(
+ 'ACTION_NAME' => 'uninstall',
+ 'L_ACTION' => $user->lang['STYLE_UNINSTALL'],
+ )
+ );
}
-
- return $component_in_use;
}
/**
- * Export style or style elements
+ * Show list of styles that can be installed
*/
- function export($mode, $style_id)
+ function show_available()
{
- global $db, $template, $user, $phpbb_root_path, $cache, $phpEx, $config;
-
- $update = (isset($_POST['update'])) ? true : false;
-
- $inc_template = request_var('inc_template', 0);
- $inc_theme = request_var('inc_theme', 0);
- $store = request_var('store', 0);
- $format = request_var('format', '');
-
- $error = array();
- $methods = array('tar');
-
- $available_methods = array('tar.gz' => 'zlib', 'tar.bz2' => 'bz2', 'zip' => 'zlib');
- foreach ($available_methods as $type => $module)
- {
- if (!@extension_loaded($module))
- {
- continue;
- }
-
- $methods[] = $type;
- }
-
- if (!in_array($format, $methods))
+ global $user, $template;
+
+ // Get list of styles
+ $styles = $this->find_available(true);
+
+ // Show styles
+ if (empty($styles))
{
- $format = 'tar';
+ trigger_error($user->lang['NO_UNINSTALLED_STYLE'] . adm_back_link($this->u_base_action), E_USER_NOTICE);
}
+
+ usort($styles, 'acp_styles::sort_styles');
- switch ($mode)
- {
- case 'style':
- if ($update && ($inc_template + $inc_theme) < 1)
- {
- $error[] = $user->lang['STYLE_ERR_MORE_ELEMENTS'];
- }
-
- $name = 'style_name';
-
- $sql_select = 's.style_id, s.style_name, s.style_copyright';
- $sql_select .= ($inc_template) ? ', t.*' : ', t.template_name';
- $sql_select .= ($inc_theme) ? ', c.*' : ', c.theme_name';
- $sql_from = STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c';
- $sql_where = "s.style_id = $style_id AND t.template_id = s.template_id AND c.theme_id = s.theme_id";
-
- $l_prefix = 'STYLE';
- break;
-
- case 'template':
- $name = 'template_name';
-
- $sql_select = '*';
- $sql_from = STYLES_TEMPLATE_TABLE;
- $sql_where = "template_id = $style_id";
-
- $l_prefix = 'TEMPLATE';
- break;
-
- case 'theme':
- $name = 'theme_name';
-
- $sql_select = '*';
- $sql_from = STYLES_THEME_TABLE;
- $sql_where = "theme_id = $style_id";
-
- $l_prefix = 'THEME';
- break;
- }
-
- if ($update && !sizeof($error))
+ $this->styles_list_cols = 3;
+ $template->assign_vars(array(
+ 'STYLES_LIST_COLS' => $this->styles_list_cols,
+ 'STYLES_LIST_HIDE_COUNT' => true
+ )
+ );
+
+ // Show styles
+ foreach ($styles as &$style)
{
- $sql = "SELECT $sql_select
- FROM $sql_from
- WHERE $sql_where";
- $result = $db->sql_query($sql);
- $style_row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$style_row)
- {
- trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
- }
-
- $var_ary = array('style_id', 'style_name', 'style_copyright', 'template_id', 'template_name', 'template_path', 'template_copyright', 'template_inherits_id', 'bbcode_bitfield', 'theme_id', 'theme_name', 'theme_path', 'theme_copyright');
-
- foreach ($var_ary as $var)
- {
- if (!isset($style_row[$var]))
- {
- $style_row[$var] = '';
- }
- }
-
- $files = $data = array();
-
- if ($mode == 'style')
- {
- $style_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['style_name'], $style_row['style_copyright'], $config['version']), $this->style_cfg);
-
- $style_cfg .= (!$inc_template) ? "\nrequired_template = {$style_row['template_name']}" : '';
- $style_cfg .= (!$inc_theme) ? "\nrequired_theme = {$style_row['theme_name']}" : '';
-
- $data[] = array(
- 'src' => $style_cfg,
- 'prefix' => 'style.cfg'
- );
-
- unset($style_cfg);
- }
-
- // Export template core code
- if ($mode == 'template' || $inc_template)
- {
- $template_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['template_name'], $style_row['template_copyright'], $config['version']), $this->template_cfg);
-
- $use_template_name = '';
-
- // Add the inherit from variable, depending on it's use...
- if ($style_row['template_inherits_id'])
- {
- // Get the template name
- $sql = 'SELECT template_name
- FROM ' . STYLES_TEMPLATE_TABLE . '
- WHERE template_id = ' . (int) $style_row['template_inherits_id'];
- $result = $db->sql_query($sql);
- $use_template_name = (string) $db->sql_fetchfield('template_name');
- $db->sql_freeresult($result);
- }
-
- $template_cfg .= ($use_template_name) ? "\ninherit_from = $use_template_name" : "\n#inherit_from = ";
- $template_cfg .= "\n\nbbcode_bitfield = {$style_row['bbcode_bitfield']}";
-
- $data[] = array(
- 'src' => $template_cfg,
- 'prefix' => 'template/template.cfg'
- );
-
- // This is potentially nasty memory-wise ...
- $files[] = array(
- 'src' => "styles/{$style_row['template_path']}/template/",
- 'prefix-' => "styles/{$style_row['template_path']}/",
- 'prefix+' => false,
- 'exclude' => 'template.cfg'
- );
- unset($template_cfg);
- }
-
- // Export theme core code
- if ($mode == 'theme' || $inc_theme)
- {
- $theme_cfg = str_replace(array('{MODE}', '{NAME}', '{COPYRIGHT}', '{VERSION}'), array($mode, $style_row['theme_name'], $style_row['theme_copyright'], $config['version']), $this->theme_cfg);
-
- // Read old cfg file
- $items = $cache->obtain_cfg_items($style_row);
- $items = $items['theme'];
-
- $files[] = array(
- 'src' => "styles/{$style_row['theme_path']}/theme/",
- 'prefix-' => "styles/{$style_row['theme_path']}/",
- 'prefix+' => false,
- 'exclude' => 'theme.cfg',
- );
-
- $data[] = array(
- 'src' => $theme_cfg,
- 'prefix' => 'theme/theme.cfg',
- );
-
- unset($items, $theme_cfg);
- }
-
- switch ($format)
- {
- case 'tar':
- $ext = '.tar';
- break;
-
- case 'zip':
- $ext = '.zip';
- break;
-
- case 'tar.gz':
- $ext = '.tar.gz';
- break;
-
- case 'tar.bz2':
- $ext = '.tar.bz2';
- break;
-
- default:
- $error[] = $user->lang[$l_prefix . '_ERR_ARCHIVE'];
- }
-
- if (!sizeof($error))
+ // Check if style has a parent style in styles list
+ $has_parent = false;
+ if ($style['_inherit_name'] != '')
{
- include($phpbb_root_path . 'includes/functions_compress.' . $phpEx);
-
- if ($mode == 'style')
- {
- $path = preg_replace('#[^\w-]+#', '_', $style_row['style_name']);
- }
- else
+ foreach ($styles as $parent_style)
{
- $path = $style_row[$mode . '_path'];
- }
-
- if ($format == 'zip')
- {
- $compress = new compress_zip('w', $phpbb_root_path . "store/$path$ext");
- }
- else
- {
- $compress = new compress_tar('w', $phpbb_root_path . "store/$path$ext", $ext);
- }
-
- if (sizeof($files))
- {
- foreach ($files as $file_ary)
- {
- $compress->add_file($file_ary['src'], $file_ary['prefix-'], $file_ary['prefix+'], $file_ary['exclude']);
- }
- }
-
- if (sizeof($data))
- {
- foreach ($data as $data_ary)
+ if ($parent_style['style_name'] == $style['_inherit_name'] && empty($parent_style['_shown']))
{
- $compress->add_data($data_ary['src'], $data_ary['prefix']);
+ // Show parent style first
+ $has_parent = true;
}
}
-
- $compress->close();
-
- add_log('admin', 'LOG_' . $l_prefix . '_EXPORT', $style_row[$mode . '_name']);
-
- if (!$store)
- {
- $compress->download($path);
- @unlink("{$phpbb_root_path}store/$path$ext");
- exit;
- }
-
- trigger_error(sprintf($user->lang[$l_prefix . '_EXPORTED'], "store/$path$ext") . adm_back_link($this->u_action));
+ }
+ if (!$has_parent)
+ {
+ $this->list_style(&$style, 0);
+ $this->show_available_child_styles(&$styles, $style['style_name'], 1);
}
}
-
- $sql = "SELECT {$mode}_id, {$mode}_name
- FROM " . (($mode == 'style') ? STYLES_TABLE : $sql_from) . "
- WHERE {$mode}_id = $style_id";
- $result = $db->sql_query($sql);
- $style_row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$style_row)
+
+ // Show styles that do not have parent style in styles list
+ foreach ($styles as $style)
{
- trigger_error($user->lang['NO_' . $l_prefix] . adm_back_link($this->u_action), E_USER_WARNING);
+ if (empty($style['_shown']))
+ {
+ $this->list_style(&$style, 0);
+ }
}
-
- $this->page_title = $l_prefix . '_EXPORT';
-
- $format_buttons = '';
- foreach ($methods as $method)
+
+ // Add button
+ if (isset($this->style_counters) && $this->style_counters['caninstall'] > 0)
{
- $format_buttons .= '<label><input type="radio"' . ((!$format_buttons) ? ' id="format"' : '') . ' class="radio" value="' . $method . '" name="format"' . (($method == $format) ? ' checked="checked"' : '') . ' /> ' . $method . '</label>';
+ $template->assign_block_vars('extra_actions', array(
+ 'ACTION_NAME' => 'install',
+ 'L_ACTION' => $user->lang['INSTALL_STYLES'],
+ )
+ );
}
-
- $template->assign_vars(array(
- 'S_EXPORT' => true,
- 'S_ERROR_MSG' => (sizeof($error)) ? true : false,
- 'S_STYLE' => ($mode == 'style') ? true : false,
-
- 'L_TITLE' => $user->lang[$this->page_title],
- 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
- 'L_NAME' => $user->lang[$l_prefix . '_NAME'],
-
- 'U_ACTION' => $this->u_action . '&amp;action=export&amp;id=' . $style_id,
- 'U_BACK' => $this->u_action,
-
- 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '',
- 'NAME' => $style_row[$mode . '_name'],
- 'FORMAT_BUTTONS' => $format_buttons)
- );
}
-
+
/**
- * Display details
+ * Find styles available for installation
+ *
+ * @param bool $all if true, function will return all installable styles. if false, function will return only styles that can be installed
+ * @returns array list of styles
*/
- function details($mode, $style_id)
+ function find_available($all)
{
- global $template, $db, $config, $user, $safe_mode, $cache, $phpbb_root_path;
-
- $update = (isset($_POST['update'])) ? true : false;
- $l_type = strtoupper($mode);
-
- $error = array();
- $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE);
-
- switch ($mode)
- {
- case 'style':
- $sql_from = STYLES_TABLE;
- break;
-
- case 'template':
- $sql_from = STYLES_TEMPLATE_TABLE;
- break;
-
- case 'theme':
- $sql_from = STYLES_THEME_TABLE;
- break;
- }
+ global $user;
- $sql = "SELECT *
- FROM $sql_from
- WHERE {$mode}_id = $style_id";
- $result = $db->sql_query($sql);
- $style_row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
+ // Get list of installed styles
+ $installed = $this->get_styles();
- if (!$style_row)
+ $installed_dirs = array();
+ $installed_names = array();
+ foreach ($installed as $style)
{
- trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING);
+ $installed_dirs[] = $style['style_path'];
+ $installed_names[$style['style_name']] = array(
+ 'path' => $style['style_path'],
+ 'id' => $style['style_id'],
+ 'parent' => $style['style_parent_id'],
+ 'tree' => (strlen($style['style_parent_tree']) ? $style['style_parent_tree'] . '/' : '') . $style['style_path'],
+ );
}
-
- $style_row['style_default'] = ($mode == 'style' && $config['default_style'] == $style_id) ? 1 : 0;
-
- if ($update)
+
+ // Get list of directories
+ $dirs = $this->find_style_dirs();
+
+ // Find styles that can be installed
+ $styles = array();
+ foreach ($dirs as $dir)
{
- $name = utf8_normalize_nfc(request_var('name', '', true));
- $copyright = utf8_normalize_nfc(request_var('copyright', '', true));
-
- $template_id = request_var('template_id', 0);
- $theme_id = request_var('theme_id', 0);
-
- $style_active = request_var('style_active', 0);
- $style_default = request_var('style_default', 0);
-
- // If the admin selected the style to be the default style, but forgot to activate it... we will do it for him
- if ($style_default)
- {
- $style_active = 1;
- }
-
- $sql = "SELECT {$mode}_id, {$mode}_name
- FROM $sql_from
- WHERE {$mode}_id <> $style_id
- AND LOWER({$mode}_name) = '" . $db->sql_escape(strtolower($name)) . "'";
- $result = $db->sql_query($sql);
- $conflict = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($mode == 'style' && (!$template_id || !$theme_id))
- {
- $error[] = $user->lang['STYLE_ERR_NO_IDS'];
- }
-
- if ($mode == 'style' && $style_row['style_active'] && !$style_active && $config['default_style'] == $style_id)
+ if (in_array($dir, $installed_dirs))
{
- $error[] = $user->lang['DEACTIVATE_DEFAULT'];
- }
-
- if (!$name || $conflict)
- {
- $error[] = $user->lang[$l_type . '_ERR_STYLE_NAME'];
+ // Style is already installed
+ continue;
}
-
- if (!sizeof($error))
+ $cfg = $this->read_style_cfg($dir);
+ if ($cfg === false)
{
- // Check length settings
- if (utf8_strlen($name) > 30)
- {
- $error[] = $user->lang[$l_type . '_ERR_NAME_LONG'];
- }
-
- if (utf8_strlen($copyright) > 60)
- {
- $error[] = $user->lang[$l_type . '_ERR_COPY_LONG'];
- }
+ // Invalid style.cfg
+ continue;
}
- }
-
- if ($update && sizeof($error))
- {
- $style_row = array_merge($style_row, array(
- 'template_id' => $template_id,
- 'theme_id' => $theme_id,
- 'style_active' => $style_active,
- $mode . '_name' => $name,
- $mode . '_copyright' => $copyright)
- );
- }
- // User has submitted form and no errors have occurred
- if ($update && !sizeof($error))
- {
- $sql_ary = array(
- $mode . '_name' => $name,
- $mode . '_copyright' => $copyright
+ // Style should be available for installation
+ $parent = $cfg['parent'];
+ $style = array(
+ 'style_id' => 0,
+ 'style_name' => $cfg['name'],
+ 'style_copyright' => $cfg['copyright'],
+ 'style_active' => 0,
+ 'style_path' => $dir,
+ 'bbcode_bitfield' => $cfg['template_bitfield'],
+ 'style_parent_id' => 0,
+ 'style_parent_tree' => '',
+ // Extra values for styles list
+ // All extra variable start with _ so they won't be confused with data that can be added to styles table
+ '_inherit_name' => $parent,
+ '_available' => true,
+ '_note' => '',
);
- switch ($mode)
- {
- case 'style':
-
- $sql_ary += array(
- 'template_id' => (int) $template_id,
- 'theme_id' => (int) $theme_id,
- 'style_active' => (int) $style_active,
- );
- break;
-
- case 'theme':
- break;
-
- case 'template':
- break;
- }
-
- if (sizeof($sql_ary))
+ // Check style inheritance
+ if ($parent != '')
{
- $sql = "UPDATE $sql_from
- SET " . $db->sql_build_array('UPDATE', $sql_ary) . "
- WHERE {$mode}_id = $style_id";
- $db->sql_query($sql);
-
- // Making this the default style?
- if ($mode == 'style' && $style_default)
+ if (isset($installed_names[$parent]))
{
- set_config('default_style', $style_id);
+ // Parent style is installed
+ $row = $installed_names[$parent];
+ $style['style_parent_id'] = $row['id'];
+ $style['style_parent_tree'] = $row['tree'];
}
- }
-
- $cache->destroy('sql', STYLES_TABLE);
-
- add_log('admin', 'LOG_' . $l_type . '_EDIT_DETAILS', $name);
- if (sizeof($error))
- {
- trigger_error(implode('<br />', $error) . adm_back_link($this->u_action), E_USER_WARNING);
- }
- else
- {
- trigger_error($user->lang[$l_type . '_DETAILS_UPDATED'] . adm_back_link($this->u_action));
- }
- }
-
- if ($mode == 'style')
- {
- foreach ($element_ary as $element => $table)
- {
- $sql = "SELECT {$element}_id, {$element}_name
- FROM $table
- ORDER BY {$element}_id ASC";
- $result = $db->sql_query($sql);
-
- ${$element . '_options'} = '';
- while ($row = $db->sql_fetchrow($result))
+ else
{
- $selected = ($row[$element . '_id'] == $style_row[$element . '_id']) ? ' selected="selected"' : '';
- ${$element . '_options'} .= '<option value="' . $row[$element . '_id'] . '"' . $selected . '>' . $row[$element . '_name'] . '</option>';
+ // Parent style is not installed yet
+ $style['_available'] = false;
+ $style['_note'] = sprintf($user->lang['REQUIRES_STYLE'], htmlspecialchars($parent));
}
- $db->sql_freeresult($result);
}
- }
-
- if ($mode == 'template')
- {
- $super = array();
- if (isset($style_row[$mode . '_inherits_id']) && $style_row['template_inherits_id'])
+
+ if ($all || $style['_available'])
{
- $super = $this->get_super($mode, $style_row['template_id']);
+ $styles[] = $style;
}
}
- $this->page_title = 'EDIT_DETAILS_' . $l_type;
-
- $template->assign_vars(array(
- 'S_DETAILS' => true,
- 'S_ERROR_MSG' => (sizeof($error)) ? true : false,
- 'S_STYLE' => ($mode == 'style') ? true : false,
- 'S_TEMPLATE' => ($mode == 'template') ? true : false,
- 'S_THEME' => ($mode == 'theme') ? true : false,
- 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0,
- 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0,
- 'S_SUPERTEMPLATE' => (isset($style_row[$mode . '_inherits_id']) && $style_row[$mode . '_inherits_id']) ? $super['template_name'] : 0,
-
- 'S_TEMPLATE_OPTIONS' => ($mode == 'style') ? $template_options : '',
- 'S_THEME_OPTIONS' => ($mode == 'style') ? $theme_options : '',
-
- 'U_ACTION' => $this->u_action . '&amp;action=details&amp;id=' . $style_id,
- 'U_BACK' => $this->u_action,
-
- 'L_TITLE' => $user->lang[$this->page_title],
- 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
- 'L_NAME' => $user->lang[$l_type . '_NAME'],
-
- 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '',
- 'NAME' => $style_row[$mode . '_name'],
- 'COPYRIGHT' => $style_row[$mode . '_copyright'],
- )
- );
+ return $styles;
}
-
+
/**
- * Load css file contents
+ * Show styles list
+ *
+ * @param array $styles styles list
+ * @param int $parent parent style id
+ * @param int $level style inheritance level
*/
- function load_css_file($path, $filename)
+ function show_styles_list($styles, $parent, $level)
{
- global $phpbb_root_path;
-
- $file = "{$phpbb_root_path}styles/$path/theme/$filename";
-
- if (file_exists($file) && ($content = file_get_contents($file)))
- {
- $content = trim($content);
- }
- else
+ foreach ($styles as &$style)
{
- $content = '';
- }
- if (defined('DEBUG'))
- {
- $content = "/* BEGIN @include $filename */ \n $content \n /* END @include $filename */ \n";
+ if (empty($style['_shown']) && $style['style_parent_id'] == $parent)
+ {
+ $this->list_style(&$style, $level);
+ $this->show_styles_list(&$styles, $style['style_id'], $level + 1);
+ }
}
-
- return $content;
}
-
+
/**
- * Returns a string containing the value that should be used for the theme_data column in the theme database table.
- * Includes contents of files loaded via @import
+ * Show available styles tree
*
- * @param array $theme_row is an associative array containing the theme's current database entry
- * @param mixed $stylesheet can either be the new content for the stylesheet or false to load from the standard file
- * @param string $root_path should only be used in case you want to use a different root path than "{$phpbb_root_path}styles/{$theme_row['theme_path']}"
- *
- * @return string Stylesheet data for theme_data column in the theme table
+ * @param array $styles Styles list, passed as reference
+ * @param string $name Name of parent style
+ * @param string $level Styles tree level
*/
- function db_theme_data($theme_row, $stylesheet = false, $root_path = '')
+ function show_available_child_styles($styles, $name, $level)
{
- global $phpbb_root_path;
-
- if (!$root_path)
+ foreach ($styles as &$style)
{
- $root_path = $phpbb_root_path . 'styles/' . $theme_row['theme_path'];
- }
-
- if (!$stylesheet)
- {
- $stylesheet = '';
- if (file_exists($root_path . '/theme/stylesheet.css'))
- {
- $stylesheet = file_get_contents($root_path . '/theme/stylesheet.css');
- }
- }
-
- // Match CSS imports
- $matches = array();
- preg_match_all('/@import url\((["\'])(.*)\1\);/i', $stylesheet, $matches);
-
- // remove commented stylesheets (very simple parser, allows only whitespace
- // around an @import statement)
- preg_match_all('#/\*\s*@import url\((["\'])(.*)\1\);\s\*/#i', $stylesheet, $commented);
- $matches[2] = array_diff($matches[2], $commented[2]);
-
- if (sizeof($matches))
- {
- foreach ($matches[0] as $idx => $match)
+ if (empty($style['_shown']) && $style['_inherit_name'] == $name)
{
- if (isset($matches[2][$idx]))
- {
- $stylesheet = str_replace($match, acp_styles::load_css_file($theme_row['theme_path'], $matches[2][$idx]), $stylesheet);
- }
+ $this->list_style(&$style, $level);
+ $this->show_available_child_styles(&$styles, $style['style_name'], $level + 1);
}
}
-
- // adjust paths
- return str_replace('./', 'styles/' . $theme_row['theme_path'] . '/theme/', $stylesheet);
}
-
+
/**
- * Returns an array containing all template filenames for one template that are currently cached.
+ * Update styles tree
*
- * @param string $template_path contains the name of the template's folder in /styles/
- *
- * @return array of filenames that exist in /styles/$template_path/template/ (without extension!)
+ * @param array $styles Styles list, passed as reference
+ * @param array $style Current style, false if root
+ * @returns true if something was updated, false if not
*/
- function template_cache_filelist($template_path)
+ function update_styles_tree($styles, $style = false)
{
- global $phpbb_root_path, $phpEx, $user;
-
- $cache_prefix = 'tpl_' . str_replace('_', '-', $template_path);
-
- if (!($dp = @opendir("{$phpbb_root_path}cache")))
- {
- trigger_error($user->lang['TEMPLATE_ERR_CACHE_READ'] . adm_back_link($this->u_action), E_USER_WARNING);
- }
-
- $file_ary = array();
- while ($file = readdir($dp))
+ $parent_id = ($style === false) ? 0 : $style['style_id'];
+ $parent_tree = ($style === false) ? '' : ($style['style_parent_tree'] == '' ? '' : $style['style_parent_tree']) . $style['style_path'];
+ $update = false;
+ $updated = false;
+ foreach ($styles as &$row)
{
- if ($file[0] == '.')
- {
- continue;
- }
-
- if (is_file($phpbb_root_path . 'cache/' . $file) && (strpos($file, $cache_prefix) === 0))
+ if ($row['style_parent_id'] == $parent_id)
{
- $file_ary[] = str_replace('.', '/', preg_replace('#^' . preg_quote($cache_prefix, '#') . '_(.*?)\.html\.' . $phpEx . '$#i', '\1', $file));
+ if ($row['style_parent_tree'] != $parent_tree)
+ {
+ $row['style_parent_tree'] = $parent_tree;
+ $update = true;
+ }
+ $updated |= $this->update_styles_tree(&$styles, $row);
}
}
- closedir($dp);
-
- return $file_ary;
+ if ($update)
+ {
+ global $db;
+ $sql = 'UPDATE ' . STYLES_TABLE . "
+ SET style_parent_tree = '" . $db->sql_escape($parent_tree) . "'
+ WHERE style_parent_id = {$parent_id}";
+ $db->sql_query($sql);
+ $updated = true;
+ }
+ return $updated;
}
-
+
/**
- * Destroys cached versions of template files
+ * Find all possible parent styles for style
*
- * @param array $template_row contains the template's row in the STYLES_TEMPLATE_TABLE database table
- * @param mixed $file_ary is optional and may contain an array of template file names which should be refreshed in the cache.
- * The file names should be the original template file names and not the cache file names.
+ * @param array $styles list of styles
+ * @param int $id id of style
+ * @param int $parent current parent style id
+ * @param int $level current tree level
+ * @returns array of style ids, names and levels
*/
- function clear_template_cache($template_row, $file_ary = false)
+ function find_possible_parents($styles, $id = -1, $parent = 0, $level = 0)
{
- global $phpbb_root_path, $phpEx, $user;
-
- $cache_prefix = 'tpl_' . str_replace('_', '-', $template_row['template_path']);
-
- if (!$file_ary || !is_array($file_ary))
- {
- $file_ary = $this->template_cache_filelist($template_row['template_path']);
- $log_file_list = $user->lang['ALL_FILES'];
- }
- else
- {
- $log_file_list = implode(', ', $file_ary);
- }
-
- foreach ($file_ary as $file)
- {
- $file = str_replace('/', '.', $file);
-
- $file = "{$phpbb_root_path}cache/{$cache_prefix}_$file.html.$phpEx";
- if (file_exists($file) && is_file($file))
- {
- @unlink($file);
+ $results = array();
+ foreach ($styles as $style)
+ {
+ if ($style['style_id'] != $id && $style['style_parent_id'] == $parent)
+ {
+ $results[] = array(
+ 'style_id' => $style['style_id'],
+ 'style_name' => $style['style_name'],
+ 'style_path' => $style['style_path'],
+ 'style_parent_id' => $style['style_parent_id'],
+ 'style_parent_tree' => $style['style_parent_tree'],
+ 'level' => $level
+ );
+ $results = array_merge($results, $this->find_possible_parents($styles, $id, $style['style_id'], $level + 1));
}
}
- unset($file_ary);
-
- add_log('admin', 'LOG_TEMPLATE_CACHE_CLEARED', $template_row['template_name'], $log_file_list);
+ return $results;
}
-
+
/**
- * Install Style/Template/Theme
+ * Show item in styles list
+ *
+ * @param array $style style row
+ * @param array $level style inheritance level
*/
- function install($mode)
+ function list_style($style, $level)
{
- global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template;
-
- $l_type = strtoupper($mode);
+ global $template, $config, $db, $user, $phpbb_root_path, $phpEx;
+
+ // Mark row as shown
+ if (!empty($style['_shown'])) return;
+ $style['_shown'] = true;
+
+ // Generate template variables
+ $actions = array();
+ $row = array(
+ // Style data
+ 'STYLE_ID' => $style['style_id'],
+ 'STYLE_NAME' => htmlspecialchars($style['style_name']),
+ 'STYLE_PATH' => htmlspecialchars($style['style_path']),
+ 'STYLE_COPYRIGHT' => strip_tags($style['style_copyright']),
+ 'STYLE_ACTIVE' => $style['style_active'],
+
+ // Additional data
+ 'DEFAULT' => ($style['style_id'] && $style['style_id'] == $config['default_style']),
+ 'USERS' => (isset($style['_users'])) ? $style['_users'] : '',
+ 'LEVEL' => $level,
+ 'PADDING' => (4 + 16 * $level),
+ 'SHOW_COPYRIGHT' => ($style['style_id']) ? false : true,
+ 'STYLE_PATH_FULL' => htmlspecialchars($this->styles_path_absolute . '/' . $style['style_path']) . '/',
+
+ // Comment to show below style
+ 'COMMENT' => (isset($style['_note'])) ? $style['_note'] : '',
+
+ // The following variables should be used by hooks to add custom HTML code
+ 'EXTRA' => '',
+ 'EXTRA_OPTIONS' => ''
+ );
+
+ // Status specific data
+ if ($style['style_id'])
+ {
+ // Style is installed
+
+ // Details
+ $actions[] = array(
+ 'U_ACTION' => $this->u_action . '&amp;action=details&amp;id=' . $style['style_id'],
+ 'L_ACTION' => $user->lang['DETAILS']
+ );
- $error = $installcfg = $style_row = array();
- $root_path = $cfg_file = '';
- $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE);
+ // Activate
+ $actions[] = array(
+ 'U_ACTION' => $this->u_action . '&amp;action=' . ($style['style_active'] ? 'de' : '') . 'activate&amp;id=' . $style['style_id'],
+ 'L_ACTION' => $user->lang['STYLE_' . ($style['style_active'] ? 'DE' : '') . 'ACTIVATE']
+ );
- $install_path = request_var('path', '');
- $update = (isset($_POST['update'])) ? true : false;
+/* // Export
+ $actions[] = array(
+ 'U_ACTION' => $this->u_action . '&amp;action=export&amp;id=' . $style['style_id'],
+ 'L_ACTION' => $user->lang['EXPORT']
+ ); */
- // Installing, obtain cfg file contents
- if ($install_path)
+ // Uninstall
+ $actions[] = array(
+ 'U_ACTION' => $this->u_action . '&amp;action=uninstall&amp;id=' . $style['style_id'],
+ 'L_ACTION' => $user->lang['STYLE_UNINSTALL']
+ );
+
+ // Preview
+ $actions[] = array(
+ 'U_ACTION' => append_sid("{$phpbb_root_path}index.$phpEx", 'style=' . $style['style_id']),
+ 'L_ACTION' => $user->lang['PREVIEW']
+ );
+ }
+ else
{
- $root_path = $phpbb_root_path . 'styles/' . $install_path . '/';
- $cfg_file = ($mode == 'style') ? "$root_path$mode.cfg" : "$root_path$mode/$mode.cfg";
-
- if (!file_exists($cfg_file))
+ // Style is not installed
+ if (empty($style['_available']))
{
- $error[] = $user->lang[$l_type . '_ERR_NOT_' . $l_type];
+ $actions[] = array(
+ 'HTML' => $user->lang['CANNOT_BE_INSTALLED']
+ );
}
else
{
- $installcfg = parse_cfg_file($cfg_file);
- }
- }
-
- // Installing
- if (sizeof($installcfg))
- {
- $name = $installcfg['name'];
- $copyright = $installcfg['copyright'];
- $version = $installcfg['version'];
-
- $style_row = array(
- $mode . '_id' => 0,
- $mode . '_name' => '',
- $mode . '_copyright' => ''
- );
-
- switch ($mode)
- {
- case 'style':
-
- $style_row = array(
- 'style_id' => 0,
- 'style_name' => $installcfg['name'],
- 'style_copyright' => $installcfg['copyright']
- );
-
- $reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false;
- $reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : false;
-
- // Check to see if each element is already installed, if it is grab the id
- foreach ($element_ary as $element => $table)
- {
- $style_row = array_merge($style_row, array(
- $element . '_id' => 0,
- $element . '_name' => '',
- $element . '_copyright' => '')
- );
-
- $this->test_installed($element, $error, (${'reqd_' . $element}) ? $phpbb_root_path . 'styles/' . $reqd_template . '/' : $root_path, ${'reqd_' . $element}, $style_row[$element . '_id'], $style_row[$element . '_name'], $style_row[$element . '_copyright']);
-
- if (!$style_row[$element . '_name'])
- {
- $style_row[$element . '_name'] = $reqd_template;
- }
-
- // Merge other information to installcfg... if present
- $cfg_file = $phpbb_root_path . 'styles/' . $install_path . '/' . $element . '/' . $element . '.cfg';
-
- if (file_exists($cfg_file))
- {
- $cfg_contents = parse_cfg_file($cfg_file);
-
- // Merge only specific things. We may need them later.
- foreach (array('inherit_from') as $key)
- {
- if (!empty($cfg_contents[$key]) && !isset($installcfg[$key]))
- {
- $installcfg[$key] = $cfg_contents[$key];
- }
- }
- }
- }
-
- break;
-
- case 'template':
- $this->test_installed('template', $error, $root_path, false, $style_row['template_id'], $style_row['template_name'], $style_row['template_copyright']);
- break;
-
- case 'theme':
- $this->test_installed('theme', $error, $root_path, false, $style_row['theme_id'], $style_row['theme_name'], $style_row['theme_copyright']);
- break;
+ $actions[] = array(
+ 'U_ACTION' => $this->u_action . '&amp;action=install&amp;dir=' . urlencode($style['style_path']),
+ 'L_ACTION' => $user->lang['INSTALL_STYLE']
+ );
}
}
- else
+
+ // todo: add hook
+
+ // Assign template variables
+ $template->assign_block_vars('styles_list', $row);
+ foreach($actions as $action)
{
- trigger_error($user->lang['NO_' . $l_type] . adm_back_link($this->u_action), E_USER_WARNING);
+ $template->assign_block_vars('styles_list.actions', $action);
}
-
- $style_row['style_active'] = request_var('style_active', 1);
- $style_row['style_default'] = request_var('style_default', 0);
-
- // User has submitted form and no errors have occurred
- if ($update && !sizeof($error))
+
+ // Increase counters
+ $counter = ($style['style_id']) ? ($style['style_active'] ? 'active' : 'inactive') : (empty($style['_available']) ? 'cannotinstall' : 'caninstall');
+ if (!isset($this->style_counters))
{
- if ($mode == 'style')
- {
- foreach ($element_ary as $element => $table)
- {
- ${$element . '_root_path'} = (${'reqd_' . $element}) ? $phpbb_root_path . 'styles/' . ${'reqd_' . $element} . '/' : false;
- ${$element . '_path'} = (${'reqd_' . $element}) ? ${'reqd_' . $element} : false;
- }
- $this->install_style($error, 'install', $root_path, $style_row['style_id'], $style_row['style_name'], $install_path, $style_row['style_copyright'], $style_row['style_active'], $style_row['style_default'], $style_row, $template_root_path, $template_path, $theme_root_path, $theme_path);
- }
- else
- {
- $this->install_element($mode, $error, 'install', $root_path, $style_row[$mode . '_id'], $style_row[$mode . '_name'], $install_path, $style_row[$mode . '_copyright']);
- }
-
- if (!sizeof($error))
- {
- $cache->destroy('sql', STYLES_TABLE);
-
- trigger_error($user->lang[$l_type . '_ADDED'] . adm_back_link($this->u_action));
- }
+ $this->style_counters = array(
+ 'total' => 0,
+ 'active' => 0,
+ 'inactive' => 0,
+ 'caninstall' => 0,
+ 'cannotinstall' => 0
+ );
}
-
- $this->page_title = 'INSTALL_' . $l_type;
-
+ $this->style_counters[$counter] ++;
+ $this->style_counters['total'] ++;
+ }
+
+ /**
+ * Show welcome message
+ *
+ * @param string $title main title
+ * @param string $description page description
+ */
+ function welcome_message($title, $description)
+ {
+ global $user, $template;
$template->assign_vars(array(
- 'S_DETAILS' => true,
- 'S_INSTALL' => true,
- 'S_ERROR_MSG' => (sizeof($error)) ? true : false,
- 'S_LOCATION' => (isset($installcfg['inherit_from']) && $installcfg['inherit_from']) ? false : true,
- 'S_STYLE' => ($mode == 'style') ? true : false,
- 'S_TEMPLATE' => ($mode == 'template') ? true : false,
- 'S_SUPERTEMPLATE' => (isset($installcfg['inherit_from'])) ? $installcfg['inherit_from'] : '',
- 'S_THEME' => ($mode == 'theme') ? true : false,
-
- 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0,
- 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0,
-
- 'U_ACTION' => $this->u_action . "&amp;action=install&amp;path=" . urlencode($install_path),
- 'U_BACK' => $this->u_action,
-
- 'L_TITLE' => $user->lang[$this->page_title],
- 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
- 'L_NAME' => $user->lang[$l_type . '_NAME'],
-
- 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '',
- 'NAME' => $style_row[$mode . '_name'],
- 'COPYRIGHT' => $style_row[$mode . '_copyright'],
- 'TEMPLATE_NAME' => ($mode == 'style') ? $style_row['template_name'] : '',
- 'THEME_NAME' => ($mode == 'style') ? $style_row['theme_name'] : '')
+ 'L_TITLE' => (isset($user->lang[$title])) ? $user->lang[$title] : $title,
+ 'L_EXPLAIN' => (isset($user->lang[$description])) ? $user->lang[$description] : $description
+ )
);
}
-
+
/**
- * Add new style
+ * Find all directories that have styles
+ *
+ * @returns array of directory names
*/
- function add($mode)
+ function find_style_dirs()
{
- global $phpbb_root_path, $phpEx, $config, $db, $cache, $user, $template;
-
- $l_type = strtoupper($mode);
- $element_ary = array('template' => STYLES_TEMPLATE_TABLE, 'theme' => STYLES_THEME_TABLE);
- $error = array();
-
- $style_row = array(
- $mode . '_name' => utf8_normalize_nfc(request_var('name', '', true)),
- $mode . '_copyright' => utf8_normalize_nfc(request_var('copyright', '', true)),
- 'template_id' => 0,
- 'theme_id' => 0,
- 'style_active' => request_var('style_active', 1),
- 'style_default' => request_var('style_default', 0),
- );
-
- $basis = request_var('basis', 0);
- $update = (isset($_POST['update'])) ? true : false;
-
- if ($basis)
- {
- switch ($mode)
- {
- case 'style':
- $sql_select = 'template_id, theme_id';
- $sql_from = STYLES_TABLE;
- break;
-
- case 'template':
- $sql_select = 'template_id';
- $sql_from = STYLES_TEMPLATE_TABLE;
- break;
-
- case 'theme':
- $sql_select = 'theme_id';
- $sql_from = STYLES_THEME_TABLE;
- break;
- }
-
- $sql = "SELECT $sql_select
- FROM $sql_from
- WHERE {$mode}_id = $basis";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if (!$row)
- {
- $error[] = $user->lang['NO_' . $l_type];
- }
-
- if (!sizeof($error))
- {
- $style_row['template_id'] = (isset($row['template_id'])) ? $row['template_id'] : $style_row['template_id'];
- $style_row['theme_id'] = (isset($row['theme_id'])) ? $row['theme_id'] : $style_row['theme_id'];
- }
- }
-
- if ($update)
- {
- $style_row['template_id'] = request_var('template_id', $style_row['template_id']);
- $style_row['theme_id'] = request_var('theme_id', $style_row['theme_id']);
-
- if ($mode == 'style' && (!$style_row['template_id'] || !$style_row['theme_id']))
- {
- $error[] = $user->lang['STYLE_ERR_NO_IDS'];
- }
- }
-
- // User has submitted form and no errors have occurred
- if ($update && !sizeof($error))
- {
- if ($mode == 'style')
- {
- $style_row['style_id'] = 0;
-
- $this->install_style($error, 'add', '', $style_row['style_id'], $style_row['style_name'], '', $style_row['style_copyright'], $style_row['style_active'], $style_row['style_default'], $style_row);
- }
-
- if (!sizeof($error))
- {
- $cache->destroy('sql', STYLES_TABLE);
-
- trigger_error($user->lang[$l_type . '_ADDED'] . adm_back_link($this->u_action));
- }
- }
+ $styles = array();
- if ($mode == 'style')
+ $dp = @opendir($this->styles_path);
+ if ($dp)
{
- foreach ($element_ary as $element => $table)
+ while (($file = readdir($dp)) !== false)
{
- $sql = "SELECT {$element}_id, {$element}_name
- FROM $table
- ORDER BY {$element}_id ASC";
- $result = $db->sql_query($sql);
+ $dir = $this->styles_path . $file;
+ if ($file[0] == '.' || !is_dir($dir))
+ {
+ continue;
+ }
- ${$element . '_options'} = '';
- while ($row = $db->sql_fetchrow($result))
+ if (file_exists("{$dir}/style.cfg"))
{
- $selected = ($row[$element . '_id'] == $style_row[$element . '_id']) ? ' selected="selected"' : '';
- ${$element . '_options'} .= '<option value="' . $row[$element . '_id'] . '"' . $selected . '>' . $row[$element . '_name'] . '</option>';
+ $styles[] = $file;
}
- $db->sql_freeresult($result);
}
+ closedir($dp);
}
- $this->page_title = 'ADD_' . $l_type;
-
- $template->assign_vars(array(
- 'S_DETAILS' => true,
- 'S_ADD' => true,
- 'S_ERROR_MSG' => (sizeof($error)) ? true : false,
- 'S_STYLE' => ($mode == 'style') ? true : false,
- 'S_TEMPLATE' => ($mode == 'template') ? true : false,
- 'S_THEME' => ($mode == 'theme') ? true : false,
- 'S_BASIS' => ($basis) ? true : false,
-
- 'S_STYLE_ACTIVE' => (isset($style_row['style_active'])) ? $style_row['style_active'] : 0,
- 'S_STYLE_DEFAULT' => (isset($style_row['style_default'])) ? $style_row['style_default'] : 0,
- 'S_TEMPLATE_OPTIONS' => ($mode == 'style') ? $template_options : '',
- 'S_THEME_OPTIONS' => ($mode == 'style') ? $theme_options : '',
-
- 'U_ACTION' => $this->u_action . '&amp;action=add&amp;basis=' . $basis,
- 'U_BACK' => $this->u_action,
-
- 'L_TITLE' => $user->lang[$this->page_title],
- 'L_EXPLAIN' => $user->lang[$this->page_title . '_EXPLAIN'],
- 'L_NAME' => $user->lang[$l_type . '_NAME'],
-
- 'ERROR_MSG' => (sizeof($error)) ? implode('<br />', $error) : '',
- 'NAME' => $style_row[$mode . '_name'],
- 'COPYRIGHT' => $style_row[$mode . '_copyright'])
- );
-
+ return $styles;
}
-
+
/**
-
- $reqd_template = (isset($installcfg['required_template'])) ? $installcfg['required_template'] : false;
- $reqd_theme = (isset($installcfg['required_theme'])) ? $installcfg['required_theme'] : false;
-
- // Check to see if each element is already installed, if it is grab the id
- foreach ($element_ary as $element => $table)
- {
- $style_row = array_merge($style_row, array(
- $element . '_id' => 0,
- $element . '_name' => '',
- $element . '_copyright' => '')
- );
-
- $this->test_installed($element, $error, $root_path, ${'reqd_' . $element}, $style_row[$element . '_id'], $style_row[$element . '_name'], $style_row[$element . '_copyright']);
- * Is this element installed? If not, grab its cfg details
+ * Sort styles
*/
- function test_installed($element, &$error, $root_path, $reqd_name, &$id, &$name, &$copyright)
+ function sort_styles($style1, $style2)
{
- global $db, $user;
-
- switch ($element)
- {
- case 'template':
- $sql_from = STYLES_TEMPLATE_TABLE;
- break;
-
- case 'theme':
- $sql_from = STYLES_THEME_TABLE;
- break;
- }
-
- $l_element = strtoupper($element);
-
- $chk_name = ($reqd_name !== false) ? $reqd_name : $name;
-
- $sql = "SELECT {$element}_id, {$element}_name
- FROM $sql_from
- WHERE {$element}_name = '" . $db->sql_escape($chk_name) . "'";
- $result = $db->sql_query($sql);
-
- if ($row = $db->sql_fetchrow($result))
+ if ($style1['style_active'] != $style2['style_active'])
{
- $name = $row[$element . '_name'];
- $id = $row[$element . '_id'];
+ return ($style1['style_active']) ? -1 : 1;
}
- else
+ if (isset($style1['_available']) && $style1['_available'] != $style2['_available'])
{
- if (!($cfg = @file("$root_path$element/$element.cfg")))
- {
- $error[] = sprintf($user->lang['REQUIRES_' . $l_element], $reqd_name);
- return false;
- }
-
- $cfg = parse_cfg_file("$root_path$element/$element.cfg", $cfg);
-
- $name = $cfg['name'];
- $copyright = $cfg['copyright'];
- $id = 0;
-
- unset($cfg);
+ return ($style1['_available']) ? -1 : 1;
}
- $db->sql_freeresult($result);
+ return strcasecmp(isset($style1['style_name']) ? $style1['style_name'] : $style1['name'], isset($style2['style_name']) ? $style2['style_name'] : $style2['name']);
}
-
+
/**
- * Install/Add style
+ * Read style configuration file
+ *
+ * @param string $dir style directory
+ * @returns array of style data
+ * @returns false on error
*/
- function install_style(&$error, $action, $root_path, &$id, $name, $path, $copyright, $active, $default, &$style_row, $template_root_path = false, $template_path = false, $theme_root_path = false, $theme_path = false)
+ function read_style_cfg($dir)
{
- global $config, $db, $user;
-
- $element_ary = array('template', 'theme');
-
- if (!$name)
- {
- $error[] = $user->lang['STYLE_ERR_STYLE_NAME'];
- }
-
- // Check length settings
- if (utf8_strlen($name) > 30)
- {
- $error[] = $user->lang['STYLE_ERR_NAME_LONG'];
- }
-
- if (utf8_strlen($copyright) > 60)
+ static $required = array('name', 'version', 'copyright');
+ $cfg = parse_cfg_file($this->styles_path . $dir . '/style.cfg');
+
+ // Check if it is a valid file
+ foreach ($required as $key)
{
- $error[] = $user->lang['STYLE_ERR_COPY_LONG'];
+ if (!isset($cfg[$key]))
+ {
+ return false;
+ }
}
-
- // Check if the name already exist
- $sql = 'SELECT style_id
- FROM ' . STYLES_TABLE . "
- WHERE style_name = '" . $db->sql_escape($name) . "'";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- if ($row)
+
+ // Check data
+ if (!isset($cfg['parent']) || !is_string($cfg['parent']) || $cfg['parent'] == $cfg['name'])
{
- $error[] = $user->lang['STYLE_ERR_NAME_EXIST'];
+ $cfg['parent'] = '';
}
-
- if (sizeof($error))
+ if (!isset($cfg['template_bitfield']))
{
- return false;
+ $cfg['template_bitfield'] = $this->default_bitfield();
}
-
- foreach ($element_ary as $element)
+
+ return $cfg;
+ }
+
+ /**
+ * Install style
+ *
+ * @param $style style data
+ * @returns int style id
+ */
+ function install_style($style)
+ {
+ global $db;
+
+ // Generate row
+ $sql_ary = array();
+ foreach ($style as $key => $value)
{
- // Zero id value ... need to install element ... run usual checks
- // and do the install if necessary
- if (!$style_row[$element . '_id'])
+ if ($key != 'style_id' && substr($key, 0, 1) != '_')
{
- $this->install_element($element, $error, $action, (${$element . '_root_path'}) ? ${$element . '_root_path'} : $root_path, $style_row[$element . '_id'], $style_row[$element . '_name'], (${$element . '_path'}) ? ${$element . '_path'} : $path, $style_row[$element . '_copyright']);
+ $sql_ary[$key] = $value;
}
}
-
- if (!$style_row['template_id'] || !$style_row['theme_id'])
- {
- $error[] = $user->lang['STYLE_ERR_NO_IDS'];
- }
-
- if (sizeof($error))
- {
- return false;
- }
-
+
+ // Add to database
$db->sql_transaction('begin');
- $sql_ary = array(
- 'style_name' => $name,
- 'style_copyright' => $copyright,
- 'style_active' => (int) $active,
- 'template_id' => (int) $style_row['template_id'],
- 'theme_id' => (int) $style_row['theme_id'],
- );
-
$sql = 'INSERT INTO ' . STYLES_TABLE . '
' . $db->sql_build_array('INSERT', $sql_ary);
$db->sql_query($sql);
$id = $db->sql_nextid();
- if ($default)
- {
- $sql = 'UPDATE ' . USERS_TABLE . "
- SET user_style = $id
- WHERE user_style = " . $config['default_style'];
- $db->sql_query($sql);
-
- set_config('default_style', $id);
- }
-
$db->sql_transaction('commit');
- add_log('admin', 'LOG_STYLE_ADD', $name);
+ add_log('admin', 'LOG_STYLE_ADD', $sql_ary['style_name']);
+
+ return $id;
}
/**
- * Install/add an element, doing various checks as we go
+ * Lists all styles
+ *
+ * @returns array of rows with styles data
*/
- function install_element($mode, &$error, $action, $root_path, &$id, $name, $path, $copyright)
+ function get_styles()
{
- global $phpbb_root_path, $db, $user;
-
- // we parse the cfg here (again)
- $cfg_data = parse_cfg_file("$root_path$mode/$mode.cfg");
-
- switch ($mode)
- {
- case 'template':
- $sql_from = STYLES_TEMPLATE_TABLE;
- break;
+ global $db;
+
+ $sql = 'SELECT *
+ FROM ' . STYLES_TABLE;
+ $result = $db->sql_query($sql);
- case 'theme':
- $sql_from = STYLES_THEME_TABLE;
- break;
- }
+ $rows = $db->sql_fetchrowset($result);
+ $db->sql_freeresult($result);
- $l_type = strtoupper($mode);
+ return $rows;
+ }
- if (!$name)
- {
- $error[] = $user->lang[$l_type . '_ERR_STYLE_NAME'];
- }
+ /**
+ * Count users for each style
+ *
+ * @returns array of styles in following format: [style_id] = number of users
+ */
+ function get_users()
+ {
+ global $db;
- // Check length settings
- if (utf8_strlen($name) > 30)
- {
- $error[] = $user->lang[$l_type . '_ERR_NAME_LONG'];
- }
+ $sql = 'SELECT user_style, COUNT(user_style) AS style_count
+ FROM ' . USERS_TABLE . '
+ GROUP BY user_style';
+ $result = $db->sql_query($sql);
- if (utf8_strlen($copyright) > 60)
+ $style_count = array();
+ while ($row = $db->sql_fetchrow($result))
{
- $error[] = $user->lang[$l_type . '_ERR_COPY_LONG'];
+ $style_count[$row['user_style']] = $row['style_count'];
}
-
- // Check if the name already exist
- $sql = "SELECT {$mode}_id
- FROM $sql_from
- WHERE {$mode}_name = '" . $db->sql_escape($name) . "'";
+ $db->sql_freeresult($result);
+
+ return $style_count;
+ }
+
+ /**
+ * Uninstall style
+ *
+ * @param array $style Style data
+ * @returns true on success, error message on error
+ */
+ function uninstall_style($style)
+ {
+ global $db, $user;
+
+ $id = $style['style_id'];
+ $path = $style['style_path'];
+
+ // Check if style has child styles
+ $sql = 'SELECT style_id
+ FROM ' . STYLES_TABLE . '
+ WHERE style_parent_id = ' . $id . " OR style_parent_tree = '" . $db->sql_escape($path) . "'";
$result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
+
+ $conflict = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- if ($row)
- {
- // If it exist, we just use the style on installation
- if ($action == 'install')
- {
- $id = $row[$mode . '_id'];
- return false;
- }
-
- $error[] = $user->lang[$l_type . '_ERR_NAME_EXIST'];
- }
-
- if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from'])
- {
- if ($mode === 'template')
- {
- $select_bf = ', bbcode_bitfield';
- }
- else
- {
- $select_bf = '';
- }
-
- $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path $select_bf
- FROM $sql_from
- WHERE {$mode}_name = '" . $db->sql_escape($cfg_data['inherit_from']) . "'
- AND {$mode}_inherits_id = 0";
- $result = $db->sql_query($sql);
- $row = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
- if (!$row)
- {
- $error[] = sprintf($user->lang[$l_type . '_ERR_REQUIRED_OR_INCOMPLETE'], $cfg_data['inherit_from']);
- }
- else
- {
- $inherit_id = $row["{$mode}_id"];
- $inherit_path = $row["{$mode}_path"];
- $inherit_bf = ($mode === 'template') ? $row["bbcode_bitfield"] : false;
- }
- }
- else
- {
- $inherit_id = 0;
- $inherit_path = '';
- $inherit_bf = false;
- }
-
- if (sizeof($error))
+ if ($conflict !== false)
{
- return false;
+ return sprintf($user->lang['STYLE_UNINSTALL_DEPENDENT'], $style['style_name']);
}
+
+ // Change default style for users
+ $sql = 'UPDATE ' . USERS_TABLE . '
+ SET user_style = 0
+ WHERE user_style = ' . $id;
+ $db->sql_query($sql);
+
+ // Uninstall style
+ $sql = 'DELETE FROM ' . STYLES_TABLE . '
+ WHERE style_id = ' . $id;
+ $db->sql_query($sql);
+ return true;
+ }
- $sql_ary = array(
- $mode . '_name' => $name,
- $mode . '_copyright' => $copyright,
- $mode . '_path' => $path,
- );
+ /**
+ * Delete all files in style directory
+ *
+ * @param string $path Style directory
+ * @param string $dir Directory to remove inside style's directory
+ * @returns true on success, false on error
+ */
+ function delete_style_files($path, $dir = '')
+ {
+ $dirname = $this->styles_path . $path . $dir;
+ $result = true;
+
+ $dp = @opendir($dirname);
- switch ($mode)
+ if ($dp)
{
- case 'template':
- // We check if the template author defined a different bitfield
- if (!empty($cfg_data['template_bitfield']))
+ while (($file = readdir($dp)) !== false)
+ {
+ if ($file == '.' || $file == '..')
{
- $sql_ary['bbcode_bitfield'] = $cfg_data['template_bitfield'];
+ continue;
}
- else if ($inherit_bf)
+ $filename = $dirname . '/' . $file;
+ if (is_dir($filename))
{
- $sql_ary['bbcode_bitfield'] = $inherit_bf;
+ if (!$this->delete_style_files($path, $dir . '/' . $file))
+ {
+ $result = false;
+ }
}
else
{
- $sql_ary['bbcode_bitfield'] = $this->template_bitfield;
- }
-
- if (isset($cfg_data['inherit_from']) && $cfg_data['inherit_from'])
- {
- $sql_ary += array(
- 'template_inherits_id' => $inherit_id,
- 'template_inherit_path' => $inherit_path,
- );
+ if (!@unlink($filename))
+ {
+ $result = false;
+ }
}
- break;
-
- case 'theme':
- break;
+ }
+ closedir($dp);
}
-
- $db->sql_transaction('begin');
-
- $sql = "INSERT INTO $sql_from
- " . $db->sql_build_array('INSERT', $sql_ary);
- $db->sql_query($sql);
-
- $id = $db->sql_nextid();
-
- $db->sql_transaction('commit');
-
- add_log('admin', 'LOG_' . $l_type . '_ADD_FS', $name);
+ if (!@rmdir($dirname))
+ {
+ return false;
+ }
+
+ return $result;
}
-
+
/**
- * Checks downwards dependencies
+ * Get list of items from posted data
*
- * @access public
- * @param string $mode The element type to check - only template is supported
- * @param int $id The template id
- * @returns false if no component inherits, array with name, path and id for each subtemplate otherwise
+ * @param string $name Variable name
+ * @param $default Default value for array: string or number
+ * @param bool $error If true, error will be triggered if list is empty
+ * @returns array of items
*/
- function check_inheritance($mode, $id)
+ function request_vars($name, $default, $error = false)
{
- global $db;
-
- $l_type = strtoupper($mode);
-
- switch ($mode)
- {
- case 'template':
- $sql_from = STYLES_TEMPLATE_TABLE;
- break;
-
- case 'theme':
- $sql_from = STYLES_THEME_TABLE;
- break;
- }
+ global $request, $user;
- $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path
- FROM $sql_from
- WHERE {$mode}_inherits_id = " . (int) $id;
- $result = $db->sql_query($sql);
+ $item = $request->variable($name, $default);
+ $items = $request->variable($name . 's', array($default));
- $names = array();
- while ($row = $db->sql_fetchrow($result))
+ if (count($items) == 1 && $items[0] == $default)
{
-
- $names[$row["{$mode}_id"]] = array(
- "{$mode}_id" => $row["{$mode}_id"],
- "{$mode}_name" => $row["{$mode}_name"],
- "{$mode}_path" => $row["{$mode}_path"],
- );
+ $items = array();
}
- $db->sql_freeresult($result);
- if (sizeof($names))
+ if ($item != $default && !count($items))
{
- return $names;
+ $items[] = $item;
}
- else
+
+ if ($error && !count($items))
{
- return false;
+ trigger_error($user->lang['NO_MATCHING_STYLES_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);
}
+
+ return $items;
}
/**
- * Checks upwards dependencies
+ * Generates hardcoded bitfield
*
- * @access public
- * @param string $mode The element type to check - only template is supported
- * @param int $id The template id
- * @returns false if the component does not inherit, array with name, path and id otherwise
+ * @returns bitfield string
*/
- function get_super($mode, $id)
+ function default_bitfield()
{
- global $db;
-
- $l_type = strtoupper($mode);
-
- switch ($mode)
- {
- case 'template':
- $sql_from = STYLES_TEMPLATE_TABLE;
- break;
-
- case 'theme':
- $sql_from = STYLES_THEME_TABLE;
- break;
- }
-
- $sql = "SELECT {$mode}_inherits_id
- FROM $sql_from
- WHERE {$mode}_id = " . (int) $id;
- $result = $db->sql_query_limit($sql, 1);
-
- if ($row = $db->sql_fetchrow($result))
- {
- $db->sql_freeresult($result);
- }
- else
+ static $value;
+ if (isset($value))
{
- return false;
+ return $value;
}
-
- $super_id = $row["{$mode}_inherits_id"];
-
- $sql = "SELECT {$mode}_id, {$mode}_name, {$mode}_path
- FROM $sql_from
- WHERE {$mode}_id = " . (int) $super_id;
-
- $result = $db->sql_query_limit($sql, 1);
- if ($row = $db->sql_fetchrow($result))
- {
- $db->sql_freeresult($result);
- return $row;
- }
-
- return false;
+
+ // Hardcoded template bitfield to add for new templates
+ $bitfield = new bitfield();
+ $bitfield->set(0);
+ $bitfield->set(1);
+ $bitfield->set(2);
+ $bitfield->set(3);
+ $bitfield->set(4);
+ $bitfield->set(8);
+ $bitfield->set(9);
+ $bitfield->set(11);
+ $bitfield->set(12);
+ $value = $bitfield->get_base64();
+ return $value;
}
+
}
diff --git a/phpBB/includes/acp/acp_users.php b/phpBB/includes/acp/acp_users.php
index 97f4b1b5fd..44717452e8 100644
--- a/phpBB/includes/acp/acp_users.php
+++ b/phpBB/includes/acp/acp_users.php
@@ -128,7 +128,7 @@ class acp_users
$dropdown_modes = array();
while ($row = $db->sql_fetchrow($result))
{
- if (!$this->p_master->module_auth($row['module_auth']))
+ if (!$this->p_master->module_auth_self($row['module_auth']))
{
continue;
}
@@ -1554,7 +1554,7 @@ class acp_users
|| $user_row['user_allow_viewonline'] && !$sql_ary['user_allow_viewonline'])
{
// We also need to check if the user has the permission to cloak.
- $user_auth = new auth();
+ $user_auth = new phpbb_auth();
$user_auth->acl($user_row);
$session_sql_ary = array(
diff --git a/phpBB/includes/acp/auth.php b/phpBB/includes/acp/auth.php
index 8f99450776..7d9fd267ff 100644
--- a/phpBB/includes/acp/auth.php
+++ b/phpBB/includes/acp/auth.php
@@ -19,7 +19,7 @@ if (!defined('IN_PHPBB'))
* ACP Permission/Auth class
* @package phpBB3
*/
-class auth_admin extends auth
+class auth_admin extends phpbb_auth
{
/**
* Init auth settings
@@ -130,7 +130,7 @@ class auth_admin extends auth
{
if ($user->data['user_id'] != $userdata['user_id'])
{
- $auth2 = new auth();
+ $auth2 = new phpbb_auth();
$auth2->acl($userdata);
}
else
diff --git a/phpBB/includes/acp/info/acp_styles.php b/phpBB/includes/acp/info/acp_styles.php
index 221371c4cb..3137c4781b 100644
--- a/phpBB/includes/acp/info/acp_styles.php
+++ b/phpBB/includes/acp/info/acp_styles.php
@@ -17,11 +17,11 @@ class acp_styles_info
return array(
'filename' => 'acp_styles',
'title' => 'ACP_CAT_STYLES',
- 'version' => '1.0.0',
+ 'version' => '2.0.0',
'modes' => array(
'style' => array('title' => 'ACP_STYLES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')),
- 'template' => array('title' => 'ACP_TEMPLATES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')),
- 'theme' => array('title' => 'ACP_THEMES', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_COMPONENTS')),
+ 'install' => array('title' => 'ACP_STYLES_INSTALL', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')),
+ 'cache' => array('title' => 'ACP_STYLES_CACHE', 'auth' => 'acl_a_styles', 'cat' => array('ACP_STYLE_MANAGEMENT')),
),
);
}
diff --git a/phpBB/includes/auth.php b/phpBB/includes/auth/auth.php
index 11e86a50fe..e3bccaf47b 100644
--- a/phpBB/includes/auth.php
+++ b/phpBB/includes/auth/auth.php
@@ -19,7 +19,7 @@ if (!defined('IN_PHPBB'))
* Permission/Auth class
* @package phpBB3
*/
-class auth
+class phpbb_auth
{
var $acl = array();
var $cache = array();
diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php
index 60274a308d..612ced8ad6 100644
--- a/phpBB/includes/bbcode.php
+++ b/phpBB/includes/bbcode.php
@@ -132,12 +132,13 @@ class bbcode
{
$this->template_bitfield = new bitfield($user->theme['bbcode_bitfield']);
- $template_locator = new phpbb_template_locator();
- $template_path_provider = new phpbb_template_extension_path_provider($phpbb_extension_manager, new phpbb_template_path_provider());
- $template = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $template_locator, $template_path_provider);
- $template->set_template();
- $template_locator->set_filenames(array('bbcode.html' => 'bbcode.html'));
- $this->template_filename = $template_locator->get_source_file_for_handle('bbcode.html');
+ $style_resource_locator = new phpbb_style_resource_locator();
+ $style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider());
+ $template = new phpbb_style_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider);
+ $style = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $template);
+ $style->set_style();
+ $template->set_filenames(array('bbcode.html' => 'bbcode.html'));
+ $this->template_filename = $style_resource_locator->get_source_file_for_handle('bbcode.html');
}
$bbcode_ids = $rowset = $sql = array();
diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php
index 8564cb8426..6da854b6e2 100644
--- a/phpBB/includes/db/dbal.php
+++ b/phpBB/includes/db/dbal.php
@@ -920,6 +920,41 @@ class dbal
return true;
}
+
+ /**
+ * Gets the estimated number of rows in a specified table.
+ *
+ * @param string $table_name Table name
+ *
+ * @return string Number of rows in $table_name.
+ * Prefixed with ~ if estimated (otherwise exact).
+ *
+ * @access public
+ */
+ function get_estimated_row_count($table_name)
+ {
+ return $this->get_row_count($table_name);
+ }
+
+ /**
+ * Gets the exact number of rows in a specified table.
+ *
+ * @param string $table_name Table name
+ *
+ * @return string Exact number of rows in $table_name.
+ *
+ * @access public
+ */
+ function get_row_count($table_name)
+ {
+ $sql = 'SELECT COUNT(*) AS rows_total
+ FROM ' . $this->sql_escape($table_name);
+ $result = $this->sql_query($sql);
+ $rows_total = $this->sql_fetchfield('rows_total');
+ $this->sql_freeresult($result);
+
+ return $rows_total;
+ }
}
/**
diff --git a/phpBB/includes/db/mysql.php b/phpBB/includes/db/mysql.php
index 317b8d123d..eb38e3e913 100644
--- a/phpBB/includes/db/mysql.php
+++ b/phpBB/includes/db/mysql.php
@@ -318,6 +318,76 @@ class dbal_mysql extends dbal
}
/**
+ * Gets the estimated number of rows in a specified table.
+ *
+ * @param string $table_name Table name
+ *
+ * @return string Number of rows in $table_name.
+ * Prefixed with ~ if estimated (otherwise exact).
+ *
+ * @access public
+ */
+ function get_estimated_row_count($table_name)
+ {
+ $table_status = $this->get_table_status($table_name);
+
+ if (isset($table_status['Engine']))
+ {
+ if ($table_status['Engine'] === 'MyISAM')
+ {
+ return $table_status['Rows'];
+ }
+ else if ($table_status['Engine'] === 'InnoDB' && $table_status['Rows'] > 100000)
+ {
+ return '~' . $table_status['Rows'];
+ }
+ }
+
+ return parent::get_row_count($table_name);
+ }
+
+ /**
+ * Gets the exact number of rows in a specified table.
+ *
+ * @param string $table_name Table name
+ *
+ * @return string Exact number of rows in $table_name.
+ *
+ * @access public
+ */
+ function get_row_count($table_name)
+ {
+ $table_status = $this->get_table_status($table_name);
+
+ if (isset($table_status['Engine']) && $table_status['Engine'] === 'MyISAM')
+ {
+ return $table_status['Rows'];
+ }
+
+ return parent::get_row_count($table_name);
+ }
+
+ /**
+ * Gets some information about the specified table.
+ *
+ * @param string $table_name Table name
+ *
+ * @return array
+ *
+ * @access protected
+ */
+ function get_table_status($table_name)
+ {
+ $sql = "SHOW TABLE STATUS
+ LIKE '" . $this->sql_escape($table_name) . "'";
+ $result = $this->sql_query($sql);
+ $table_status = $this->sql_fetchrow($result);
+ $this->sql_freeresult($result);
+
+ return $table_status;
+ }
+
+ /**
* Build LIKE expression
* @access private
*/
diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/mysqli.php
index d6b64bf7c8..4210a58002 100644
--- a/phpBB/includes/db/mysqli.php
+++ b/phpBB/includes/db/mysqli.php
@@ -315,6 +315,76 @@ class dbal_mysqli extends dbal
}
/**
+ * Gets the estimated number of rows in a specified table.
+ *
+ * @param string $table_name Table name
+ *
+ * @return string Number of rows in $table_name.
+ * Prefixed with ~ if estimated (otherwise exact).
+ *
+ * @access public
+ */
+ function get_estimated_row_count($table_name)
+ {
+ $table_status = $this->get_table_status($table_name);
+
+ if (isset($table_status['Engine']))
+ {
+ if ($table_status['Engine'] === 'MyISAM')
+ {
+ return $table_status['Rows'];
+ }
+ else if ($table_status['Engine'] === 'InnoDB' && $table_status['Rows'] > 100000)
+ {
+ return '~' . $table_status['Rows'];
+ }
+ }
+
+ return parent::get_row_count($table_name);
+ }
+
+ /**
+ * Gets the exact number of rows in a specified table.
+ *
+ * @param string $table_name Table name
+ *
+ * @return string Exact number of rows in $table_name.
+ *
+ * @access public
+ */
+ function get_row_count($table_name)
+ {
+ $table_status = $this->get_table_status($table_name);
+
+ if (isset($table_status['Engine']) && $table_status['Engine'] === 'MyISAM')
+ {
+ return $table_status['Rows'];
+ }
+
+ return parent::get_row_count($table_name);
+ }
+
+ /**
+ * Gets some information about the specified table.
+ *
+ * @param string $table_name Table name
+ *
+ * @return array
+ *
+ * @access protected
+ */
+ function get_table_status($table_name)
+ {
+ $sql = "SHOW TABLE STATUS
+ LIKE '" . $this->sql_escape($table_name) . "'";
+ $result = $this->sql_query($sql);
+ $table_status = $this->sql_fetchrow($result);
+ $this->sql_freeresult($result);
+
+ return $table_status;
+ }
+
+ /**
* Build LIKE expression
* @access private
*/
diff --git a/phpBB/includes/event/data.php b/phpBB/includes/event/data.php
new file mode 100644
index 0000000000..70718ff0ae
--- /dev/null
+++ b/phpBB/includes/event/data.php
@@ -0,0 +1,68 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+use Symfony\Component\EventDispatcher\Event;
+
+class phpbb_event_data extends Event implements ArrayAccess
+{
+ private $data;
+
+ public function __construct(array $data = array())
+ {
+ $this->set_data($data);
+ }
+
+ public function set_data(array $data = array())
+ {
+ $this->data = $data;
+ }
+
+ public function get_data()
+ {
+ return $this->data;
+ }
+
+ /**
+ * Returns data filtered to only include specified keys.
+ *
+ * This effectively discards any keys added to data by hooks.
+ */
+ public function get_data_filtered($keys)
+ {
+ return array_intersect_key($this->data, array_flip($keys));
+ }
+
+ public function offsetExists($offset)
+ {
+ return isset($this->data[$offset]);
+ }
+
+ public function offsetGet($offset)
+ {
+ return isset($this->data[$offset]) ? $this->data[$offset] : null;
+ }
+
+ public function offsetSet($offset, $value)
+ {
+ $this->data[$offset] = $value;
+ }
+
+ public function offsetUnset($offset)
+ {
+ unset($this->data[$offset]);
+ }
+}
diff --git a/phpBB/includes/event/dispatcher.php b/phpBB/includes/event/dispatcher.php
new file mode 100644
index 0000000000..2bf46b9b06
--- /dev/null
+++ b/phpBB/includes/event/dispatcher.php
@@ -0,0 +1,42 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+use Symfony\Component\EventDispatcher\EventDispatcher;
+
+/**
+* Extension of the Symfony2 EventDispatcher
+*
+* It provides an additional `trigger_event` method, which
+* gives some syntactic sugar for dispatching events. Instead
+* of creating the event object, the method will do that for
+* you.
+*
+* Example:
+*
+* $vars = array('page_title');
+* extract($phpbb_dispatcher->trigger_event('core.index', compact($vars)));
+*
+*/
+class phpbb_event_dispatcher extends EventDispatcher
+{
+ public function trigger_event($eventName, $data = array())
+ {
+ $event = new phpbb_event_data($data);
+ $this->dispatch($eventName, $event);
+ return $event->get_data_filtered(array_keys($data));
+ }
+}
diff --git a/phpBB/includes/event/extension_subscriber_loader.php b/phpBB/includes/event/extension_subscriber_loader.php
new file mode 100644
index 0000000000..d933b943d7
--- /dev/null
+++ b/phpBB/includes/event/extension_subscriber_loader.php
@@ -0,0 +1,46 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2012 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+
+class phpbb_event_extension_subscriber_loader
+{
+ private $dispatcher;
+ private $extension_manager;
+
+ public function __construct(EventDispatcherInterface $dispatcher, phpbb_extension_manager $extension_manager)
+ {
+ $this->dispatcher = $dispatcher;
+ $this->extension_manager = $extension_manager;
+ }
+
+ public function load()
+ {
+ $finder = $this->extension_manager->get_finder();
+ $subscriber_classes = $finder
+ ->extension_directory('/event')
+ ->suffix('listener')
+ ->core_path('event/')
+ ->get_classes();
+
+ foreach ($subscriber_classes as $class)
+ {
+ $subscriber = new $class();
+ $this->dispatcher->addSubscriber($subscriber);
+ }
+ }
+}
diff --git a/phpBB/includes/extension/controller.php b/phpBB/includes/extension/controller.php
new file mode 100644
index 0000000000..c7fd439a19
--- /dev/null
+++ b/phpBB/includes/extension/controller.php
@@ -0,0 +1,77 @@
+<?php
+/**
+*
+* @package extension
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Abstract class extended by extension front controller classes
+*
+* @package extension
+*/
+abstract class phpbb_extension_controller implements phpbb_extension_controller_interface
+{
+ /**
+ * @var phpbb_request Request class object
+ */
+ protected $request;
+
+ /**
+ * @var dbal DBAL class object
+ */
+ protected $db;
+
+ /**
+ * @var user User class object
+ */
+ protected $user;
+
+ /**
+ * @var phpbb_template Template class object
+ */
+ protected $template;
+
+ /**
+ * @var array Config array
+ */
+ protected $config;
+
+ /**
+ * @var string PHP Extension
+ */
+ protected $phpEx;
+
+ /**
+ * @var string Relative path to board root
+ */
+ protected $phpbb_root_path;
+
+ /**
+ * Constructor method that provides the common phpBB objects as inherited class
+ * properties for automatic availability in extension controllers
+ */
+ public function __construct()
+ {
+ global $request, $db, $user, $template, $config;
+ global $phpEx, $phpbb_root_path;
+
+ $this->request = $request;
+ $this->db = $db;
+ $this->user = $user;
+ $this->template = $template;
+ $this->config = $config;
+ $this->phpEx = $phpEx;
+ $this->phpbb_root_path = $phpbb_root_path;
+ }
+}
diff --git a/phpBB/includes/extension/controller_interface.php b/phpBB/includes/extension/controller_interface.php
new file mode 100644
index 0000000000..2b88925388
--- /dev/null
+++ b/phpBB/includes/extension/controller_interface.php
@@ -0,0 +1,31 @@
+<?php
+/**
+*
+* @package extension
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* The interface that extension classes have to implement to run front pages
+*
+* @package extension
+*/
+interface phpbb_extension_controller_interface
+{
+ /**
+ * Handle the request to display a page from an extension
+ *
+ * @return null
+ */
+ public function handle();
+}
diff --git a/phpBB/includes/extension/finder.php b/phpBB/includes/extension/finder.php
index e5e5e4983e..23b9f1c658 100644
--- a/phpBB/includes/extension/finder.php
+++ b/phpBB/includes/extension/finder.php
@@ -375,6 +375,10 @@ class phpbb_extension_finder
{
$directory_pattern = preg_quote(DIRECTORY_SEPARATOR . str_replace('/', DIRECTORY_SEPARATOR, $directory) . DIRECTORY_SEPARATOR, '#');
}
+ if ($is_dir)
+ {
+ $directory_pattern .= '$';
+ }
$directory_pattern = '#' . $directory_pattern . '#';
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path), RecursiveIteratorIterator::SELF_FIRST);
diff --git a/phpBB/includes/extension/manager.php b/phpBB/includes/extension/manager.php
index 438578e7e7..537c19aff8 100644
--- a/phpBB/includes/extension/manager.php
+++ b/phpBB/includes/extension/manager.php
@@ -61,7 +61,7 @@ class phpbb_extension_manager
*
* @return null
*/
- protected function load_extensions()
+ public function load_extensions()
{
$sql = 'SELECT *
FROM ' . $this->extension_table;
@@ -167,6 +167,11 @@ class phpbb_extension_manager
$this->db->sql_query($sql);
}
+ if ($this->cache)
+ {
+ $this->cache->destroy($this->cache_name);
+ }
+
return !$active;
}
@@ -219,6 +224,11 @@ class phpbb_extension_manager
WHERE ext_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
+ if ($this->cache)
+ {
+ $this->cache->destroy($this->cache_name);
+ }
+
return true;
}
@@ -234,6 +244,11 @@ class phpbb_extension_manager
WHERE ext_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
+ if ($this->cache)
+ {
+ $this->cache->destroy($this->cache_name);
+ }
+
return false;
}
@@ -292,6 +307,11 @@ class phpbb_extension_manager
WHERE ext_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
+ if ($this->cache)
+ {
+ $this->cache->destroy($this->cache_name);
+ }
+
return true;
}
@@ -301,6 +321,11 @@ class phpbb_extension_manager
WHERE ext_name = '" . $this->db->sql_escape($name) . "'";
$this->db->sql_query($sql);
+ if ($this->cache)
+ {
+ $this->cache->destroy($this->cache_name);
+ }
+
return false;
}
@@ -327,9 +352,14 @@ class phpbb_extension_manager
public function all_available()
{
$available = array();
+ if (!is_dir($this->phpbb_root_path . 'ext/'))
+ {
+ return $available;
+ }
$iterator = new RecursiveIteratorIterator(
- new RecursiveDirectoryIterator($this->phpbb_root_path . 'ext/'));
+ new RecursiveDirectoryIterator($this->phpbb_root_path . 'ext/'),
+ RecursiveIteratorIterator::SELF_FIRST);
foreach ($iterator as $file_info)
{
if ($file_info->isFile() && $file_info->getFilename() == 'ext' . $this->phpEx)
@@ -402,6 +432,28 @@ class phpbb_extension_manager
}
return $disabled;
}
+
+ /**
+ * Check to see if a given extension is available on the filesystem
+ *
+ * @param string $name Extension name to check NOTE: Can be user input
+ * @return bool Depending on whether or not the extension is available
+ */
+ public function available($name)
+ {
+ return file_exists($this->get_extension_path($name, true));
+ }
+
+ /**
+ * Check to see if a given extension is enabled
+ *
+ * @param string $name Extension name to check
+ * @return bool Depending on whether or not the extension is enabled
+ */
+ public function enabled($name)
+ {
+ return isset($this->extensions[$name]) && $this->extensions[$name]['ext_active'];
+ }
/**
* Instantiates a phpbb_extension_finder.
diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php
index a60edb5cee..74db8cb8fd 100644
--- a/phpBB/includes/functions.php
+++ b/phpBB/includes/functions.php
@@ -2448,15 +2448,25 @@ function build_url($strip_vars = false)
*/
function meta_refresh($time, $url, $disable_cd_check = false)
{
- global $template;
+ global $template, $refresh_data, $request;
- $url = redirect($url, true, $disable_cd_check);
- $url = str_replace('&', '&amp;', $url);
+ if ($request->is_ajax())
+ {
+ $refresh_data = array(
+ 'time' => $time,
+ 'url' => str_replace('&amp;', '&', $url)
+ );
+ }
+ else
+ {
+ $url = redirect($url, true, $disable_cd_check);
+ $url = str_replace('&', '&amp;', $url);
- // For XHTML compatibility we change back & to &amp;
- $template->assign_vars(array(
- 'META' => '<meta http-equiv="refresh" content="' . $time . ';url=' . $url . '" />')
- );
+ // For XHTML compatibility we change back & to &amp;
+ $template->assign_vars(array(
+ 'META' => '<meta http-equiv="refresh" content="' . $time . ';url=' . $url . '" />')
+ );
+ }
return $url;
}
@@ -2619,7 +2629,7 @@ function check_form_key($form_name, $timespan = false, $return_page = '', $trigg
*/
function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_body.html', $u_action = '')
{
- global $user, $template, $db;
+ global $user, $template, $db, $request;
global $phpEx, $phpbb_root_path, $request;
if (isset($_POST['cancel']))
@@ -2699,6 +2709,21 @@ function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_bo
WHERE user_id = " . $user->data['user_id'];
$db->sql_query($sql);
+
+ if ($request->is_ajax())
+ {
+ $u_action .= '&confirm_uid=' . $user->data['user_id'] . '&sess=' . $user->session_id . '&sid=' . $user->session_id;
+ $json_response = new phpbb_json_response;
+ $json_response->send(array(
+ 'MESSAGE_TITLE' => (!isset($user->lang[$title])) ? $user->lang['CONFIRM'] : $user->lang[$title],
+ 'MESSAGE_TEXT' => (!isset($user->lang[$title . '_CONFIRM'])) ? $title : $user->lang[$title . '_CONFIRM'],
+
+ 'YES_VALUE' => $user->lang['YES'],
+ 'S_CONFIRM_ACTION' => str_replace('&amp;', '&', $u_action), //inefficient, rewrite whole function
+ 'S_HIDDEN_FIELDS' => $hidden . $s_hidden_fields
+ ));
+ }
+
if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin'])
{
adm_page_footer();
@@ -3091,6 +3116,11 @@ function parse_cfg_file($filename, $lines = false)
$parsed_items[$key] = $value;
}
+
+ if (isset($parsed_items['parent']) && isset($parsed_items['name']) && $parsed_items['parent'] == $parsed_items['name'])
+ {
+ unset($parsed_items['parent']);
+ }
return $parsed_items;
}
@@ -3718,7 +3748,7 @@ function phpbb_checkdnsrr($host, $type = 'MX')
*/
function msg_handler($errno, $msg_text, $errfile, $errline)
{
- global $cache, $db, $auth, $template, $config, $user;
+ global $cache, $db, $auth, $template, $config, $user, $request;
global $phpEx, $phpbb_root_path, $msg_title, $msg_long_text;
// Do not display notices if we suppress them via @
@@ -3917,6 +3947,20 @@ function msg_handler($errno, $msg_text, $errfile, $errline)
'S_USER_NOTICE' => ($errno == E_USER_NOTICE) ? true : false)
);
+ if ($request->is_ajax())
+ {
+ global $refresh_data;
+
+ $json_response = new phpbb_json_response;
+ $json_response->send(array(
+ 'MESSAGE_TITLE' => $msg_title,
+ 'MESSAGE_TEXT' => $msg_text,
+ 'S_USER_WARNING' => ($errno == E_USER_WARNING) ? true : false,
+ 'S_USER_NOTICE' => ($errno == E_USER_NOTICE) ? true : false,
+ 'REFRESH_DATA' => (!empty($refresh_data)) ? $refresh_data : null
+ ));
+ }
+
// We do not want the cron script to be called on error messages
define('IN_CRON', true);
@@ -4473,6 +4517,7 @@ function phpbb_http_login($param)
function page_header($page_title = '', $display_online_list = true, $item_id = 0, $item = 'forum')
{
global $db, $config, $template, $SID, $_SID, $_EXTRA_URL, $user, $auth, $phpEx, $phpbb_root_path;
+ global $phpbb_dispatcher;
if (defined('HEADER_INC'))
{
@@ -4627,7 +4672,7 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
foreach ($_EXTRA_URL as $url_param)
{
$url_param = explode('=', $url_param, 2);
- $s_hidden_fields[$url_param[0]] = $url_param[1];
+ $s_search_hidden_fields[$url_param[0]] = $url_param[1];
}
}
@@ -4723,9 +4768,9 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'S_SEARCH_HIDDEN_FIELDS' => build_hidden_fields($s_search_hidden_fields),
'T_ASSETS_PATH' => "{$web_path}assets",
- 'T_THEME_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['theme_path']) . '/theme',
- 'T_TEMPLATE_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['template_path']) . '/template',
- 'T_SUPER_TEMPLATE_PATH' => (isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? "{$web_path}styles/" . rawurlencode($user->theme['template_inherit_path']) . '/template' : "{$web_path}styles/" . rawurlencode($user->theme['template_path']) . '/template',
+ 'T_THEME_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/theme',
+ 'T_TEMPLATE_PATH' => "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/template',
+ 'T_SUPER_TEMPLATE_PATH' => ($user->theme['style_parent_id']) ? "{$web_path}styles/" . rawurlencode($user->theme['style_parent_tree']) . '/template' : "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/template',
'T_IMAGES_PATH' => "{$web_path}images/",
'T_SMILIES_PATH' => "{$web_path}{$config['smilies_path']}/",
'T_AVATAR_PATH' => "{$web_path}{$config['avatar_path']}/",
@@ -4733,16 +4778,16 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'T_ICONS_PATH' => "{$web_path}{$config['icons_path']}/",
'T_RANKS_PATH' => "{$web_path}{$config['ranks_path']}/",
'T_UPLOAD_PATH' => "{$web_path}{$config['upload_path']}/",
- 'T_STYLESHEET_LINK' => "{$web_path}styles/" . rawurlencode($user->theme['theme_path']) . '/theme/stylesheet.css',
- 'T_STYLESHEET_LANG_LINK' => "{$web_path}styles/" . rawurlencode($user->theme['theme_path']) . '/theme/' . $user->lang_name . '/stylesheet.css',
- 'T_STYLESHEET_NAME' => $user->theme['theme_name'],
+ 'T_STYLESHEET_LINK' => "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/theme/stylesheet.css',
+ 'T_STYLESHEET_LANG_LINK' => "{$web_path}styles/" . rawurlencode($user->theme['style_path']) . '/theme/' . $user->lang_name . '/stylesheet.css',
+ 'T_STYLESHEET_NAME' => $user->theme['style_name'],
'T_JQUERY_LINK' => ($config['load_jquery_cdn'] && !empty($config['load_jquery_url'])) ? $config['load_jquery_url'] : "{$web_path}assets/javascript/jquery.js",
'S_JQUERY_FALLBACK' => ($config['load_jquery_cdn']) ? true : false,
- 'T_THEME_NAME' => rawurlencode($user->theme['theme_path']),
+ 'T_THEME_NAME' => rawurlencode($user->theme['style_path']),
'T_THEME_LANG_NAME' => $user->data['user_lang'],
- 'T_TEMPLATE_NAME' => $user->theme['template_path'],
- 'T_SUPER_TEMPLATE_NAME' => rawurlencode((isset($user->theme['template_inherit_path']) && $user->theme['template_inherit_path']) ? $user->theme['template_inherit_path'] : $user->theme['template_path']),
+ 'T_TEMPLATE_NAME' => $user->theme['style_path'],
+ 'T_SUPER_TEMPLATE_NAME' => rawurlencode((isset($user->theme['style_parent_tree']) && $user->theme['style_parent_tree']) ? $user->theme['style_parent_tree'] : $user->theme['style_path']),
'T_IMAGES' => 'images',
'T_SMILIES' => $config['smilies_path'],
'T_AVATAR' => $config['avatar_path'],
@@ -4756,6 +4801,9 @@ function page_header($page_title = '', $display_online_list = true, $item_id = 0
'A_COOKIE_SETTINGS' => addslashes('; path=' . $config['cookie_path'] . ((!$config['cookie_domain'] || $config['cookie_domain'] == 'localhost' || $config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . $config['cookie_domain']) . ((!$config['cookie_secure']) ? '' : '; secure')),
));
+ $vars = array('page_title', 'display_online_list', 'item_id', 'item');
+ extract($phpbb_dispatcher->trigger_event('core.page_header', compact($vars)));
+
// application/xhtml+xml not used because of IE
header('Content-type: text/html; charset=UTF-8');
@@ -4901,7 +4949,7 @@ function exit_handler()
}
/**
-* Handler for init calls in phpBB. This function is called in user::setup();
+* Handler for init calls in phpBB. This function is called in phpbb_user::setup();
* This function supports hooks.
*/
function phpbb_user_session_handler()
diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php
index 7fdf874456..9798e514c1 100644
--- a/phpBB/includes/functions_admin.php
+++ b/phpBB/includes/functions_admin.php
@@ -847,15 +847,13 @@ function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync =
}
// Remove the message from the search index
- $search_type = basename($config['search_type']);
+ $search_type = $config['search_type'];
- if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx))
+ if (!class_exists($search_type))
{
trigger_error('NO_SUCH_SEARCH_MODULE');
}
- include_once("{$phpbb_root_path}includes/search/$search_type.$phpEx");
-
$error = false;
$search = new $search_type($error);
@@ -2330,7 +2328,7 @@ function cache_moderators()
$ug_id_ary = array_keys($hold_ary);
// Remove users who have group memberships with DENY moderator permissions
- $sql_ary = array(
+ $sql_ary_deny = array(
'SELECT' => 'a.forum_id, ug.user_id, g.group_id',
'FROM' => array(
@@ -2357,7 +2355,7 @@ function cache_moderators()
AND ug.user_pending = 0
AND o.auth_option " . $db->sql_like_expression('m_' . $db->any_char),
);
- $sql = $db->sql_build_query('SELECT', $sql_ary);
+ $sql = $db->sql_build_query('SELECT', $sql_ary_deny);
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php
index 3a0124934e..f2faf20f43 100644
--- a/phpBB/includes/functions_content.php
+++ b/phpBB/includes/functions_content.php
@@ -1103,8 +1103,8 @@ function extension_allowed($forum_id, $extension, &$extensions)
* @param string $string The text to truncate to the given length. String is specialchared.
* @param int $max_length Maximum length of string (multibyte character count as 1 char / Html entity count as 1 char)
* @param int $max_store_length Maximum character length of string (multibyte character count as 1 char / Html entity count as entity chars).
-* @param bool $allow_reply Allow Re: in front of string
-* NOTE: This parameter can cause undesired behavior (returning strings longer than $max_store_length) and is deprecated.
+* @param bool $allow_reply Allow Re: in front of string
+* NOTE: This parameter can cause undesired behavior (returning strings longer than $max_store_length) and is deprecated.
* @param string $append String to be appended
*/
function truncate_string($string, $max_length = 60, $max_store_length = 255, $allow_reply = false, $append = '')
@@ -1259,6 +1259,22 @@ function get_username_string($mode, $user_id, $username, $username_colour = '',
}
/**
+ * Add an option to the quick-mod tools.
+ *
+ * @param string $option The language key for the value of the option.
+ * @param string $lang_string The language string to use.
+ */
+function phpbb_add_quickmod_option($option, $lang_string)
+{
+ global $template, $user;
+ $lang_string = $user->lang($lang_string);
+ $template->assign_block_vars('quickmod', array(
+ 'VALUE' => $option,
+ 'TITLE' => $lang_string,
+ ));
+}
+
+/**
* @package phpBB3
*/
class bitfield
diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php
index 9335cabc15..18db64cc68 100644
--- a/phpBB/includes/functions_display.php
+++ b/phpBB/includes/functions_display.php
@@ -273,6 +273,7 @@ function display_forums($root_data = '', $display_moderators = true, $return_mod
markread('topics', $forum_ids);
$message = sprintf($user->lang['RETURN_FORUM'], '<a href="' . $redirect . '">', '</a>');
meta_refresh(3, $redirect);
+
trigger_error($user->lang['FORUMS_MARKED'] . '<br /><br />' . $message);
}
else
diff --git a/phpBB/includes/functions_download.php b/phpBB/includes/functions_download.php
index de25e390fa..1486113013 100644
--- a/phpBB/includes/functions_download.php
+++ b/phpBB/includes/functions_download.php
@@ -126,7 +126,7 @@ function send_file_to_browser($attachment, $upload_dir, $category)
if (!@file_exists($filename))
{
send_status_line(404, 'Not Found');
- trigger_error($user->lang['ERROR_NO_ATTACHMENT'] . '<br /><br />' . sprintf($user->lang['FILE_NOT_FOUND_404'], $filename));
+ trigger_error('ERROR_NO_ATTACHMENT');
}
// Correct the mime type - we force application/octetstream for all files, except images
diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php
index 13d9b6a5cb..aae200df55 100644
--- a/phpBB/includes/functions_messenger.php
+++ b/phpBB/includes/functions_messenger.php
@@ -201,17 +201,18 @@ class messenger
{
// fall back to board default language if the user's language is
// missing $template_file. If this does not exist either,
- // $tpl->set_custom_template will do a trigger_error
+ // $tpl->set_filenames will do a trigger_error
$template_lang = basename($config['default_lang']);
}
// tpl_msg now holds a template object we can use to parse the template file
if (!isset($this->tpl_msg[$template_lang . $template_file]))
{
- $template_locator = new phpbb_template_locator();
- $template_path_provider = new phpbb_template_extension_path_provider($phpbb_extension_manager, new phpbb_template_path_provider());
- $this->tpl_msg[$template_lang . $template_file] = new phpbb_template($phpbb_root_path, $phpEx, $config, $user, $template_locator, $template_path_provider);
- $tpl = &$this->tpl_msg[$template_lang . $template_file];
+ $style_resource_locator = new phpbb_style_resource_locator();
+ $style_path_provider = new phpbb_style_extension_path_provider($phpbb_extension_manager, new phpbb_style_path_provider());
+ $tpl = new phpbb_style_template($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider);
+ $stl = new phpbb_style($phpbb_root_path, $phpEx, $config, $user, $style_resource_locator, $style_path_provider, $tpl);
+ $this->tpl_msg[$template_lang . $template_file] = $tpl;
$fallback_template_path = false;
@@ -229,7 +230,7 @@ class messenger
}
}
- $tpl->set_custom_template($template_path, $template_lang . '_email', $fallback_template_path);
+ $stl->set_custom_style($template_lang . '_email', array($template_path, $fallback_template_path), '');
$tpl->set_filenames(array(
'body' => $template_file . '.txt',
@@ -1136,6 +1137,7 @@ class smtp_class
{
var $server_response = '';
var $socket = 0;
+ protected $socket_tls = false;
var $responses = array();
var $commands = array();
var $numeric_response_code = 0;
@@ -1286,30 +1288,29 @@ class smtp_class
}
}
- // Try EHLO first
- $this->server_send("EHLO {$local_host}");
- if ($err_msg = $this->server_parse('250', __LINE__))
+ $hello_result = $this->hello($local_host);
+ if (!is_null($hello_result))
{
- // a 503 response code means that we're already authenticated
- if ($this->numeric_response_code == 503)
- {
- return false;
- }
-
- // If EHLO fails, we try HELO
- $this->server_send("HELO {$local_host}");
- if ($err_msg = $this->server_parse('250', __LINE__))
- {
- return ($this->numeric_response_code == 503) ? false : $err_msg;
- }
+ return $hello_result;
}
- foreach ($this->responses as $response)
+ // SMTP STARTTLS (RFC 3207)
+ if (!$this->socket_tls)
{
- $response = explode(' ', $response);
- $response_code = $response[0];
- unset($response[0]);
- $this->commands[$response_code] = implode(' ', $response);
+ $this->socket_tls = $this->starttls();
+
+ if ($this->socket_tls)
+ {
+ // Switched to TLS
+ // RFC 3207: "The client MUST discard any knowledge obtained from the server, [...]"
+ // So say hello again
+ $hello_result = $this->hello($local_host);
+
+ if (!is_null($hello_result))
+ {
+ return $hello_result;
+ }
+ }
}
// If we are not authenticated yet, something might be wrong if no username and passwd passed
@@ -1356,6 +1357,79 @@ class smtp_class
}
/**
+ * SMTP EHLO/HELO
+ *
+ * @return mixed Null if the authentication process is supposed to continue
+ * False if already authenticated
+ * Error message (string) otherwise
+ */
+ protected function hello($hostname)
+ {
+ // Try EHLO first
+ $this->server_send("EHLO $hostname");
+ if ($err_msg = $this->server_parse('250', __LINE__))
+ {
+ // a 503 response code means that we're already authenticated
+ if ($this->numeric_response_code == 503)
+ {
+ return false;
+ }
+
+ // If EHLO fails, we try HELO
+ $this->server_send("HELO $hostname");
+ if ($err_msg = $this->server_parse('250', __LINE__))
+ {
+ return ($this->numeric_response_code == 503) ? false : $err_msg;
+ }
+ }
+
+ foreach ($this->responses as $response)
+ {
+ $response = explode(' ', $response);
+ $response_code = $response[0];
+ unset($response[0]);
+ $this->commands[$response_code] = implode(' ', $response);
+ }
+ }
+
+ /**
+ * SMTP STARTTLS (RFC 3207)
+ *
+ * @return bool Returns true if TLS was started
+ * Otherwise false
+ */
+ protected function starttls()
+ {
+ if (!function_exists('stream_socket_enable_crypto'))
+ {
+ return false;
+ }
+
+ if (!isset($this->commands['STARTTLS']))
+ {
+ return false;
+ }
+
+ $this->server_send('STARTTLS');
+
+ if ($err_msg = $this->server_parse('220', __LINE__))
+ {
+ return false;
+ }
+
+ $result = false;
+ $stream_meta = stream_get_meta_data($this->socket);
+
+ if (socket_set_blocking($this->socket, 1));
+ {
+ $result = stream_socket_enable_crypto($this->socket, true, STREAM_CRYPTO_METHOD_TLS_CLIENT);
+ socket_set_blocking($this->socket, (int) $stream_meta['blocked']);
+ }
+
+ return $result;
+ }
+
+ /**
* Pop before smtp authentication
*/
function pop_before_smtp($hostname, $username, $password)
diff --git a/phpBB/includes/functions_module.php b/phpBB/includes/functions_module.php
index b7bb770031..ad76be9f2f 100644
--- a/phpBB/includes/functions_module.php
+++ b/phpBB/includes/functions_module.php
@@ -128,7 +128,7 @@ class p_master
foreach ($this->module_cache['modules'] as $key => $row)
{
// Not allowed to view module?
- if (!$this->module_auth($row['module_auth']))
+ if (!$this->module_auth_self($row['module_auth']))
{
unset($this->module_cache['modules'][$key]);
continue;
@@ -315,9 +315,23 @@ class p_master
}
/**
- * Check module authorisation
+ * Check module authorisation.
+ *
+ * This is a non-static version that uses $this->acl_forum_id
+ * for the forum id.
+ */
+ function module_auth_self($module_auth)
+ {
+ return self::module_auth($module_auth, $this->acl_forum_id);
+ }
+
+ /**
+ * Check module authorisation.
+ *
+ * This is a static version, it must be given $forum_id.
+ * See also module_auth_self.
*/
- function module_auth($module_auth, $forum_id = false)
+ static function module_auth($module_auth, $forum_id)
{
global $auth, $config;
global $request;
@@ -362,11 +376,9 @@ class p_master
$module_auth = implode(' ', $tokens);
- // Make sure $id seperation is working fine
+ // Make sure $id separation is working fine
$module_auth = str_replace(' , ', ',', $module_auth);
- $forum_id = ($forum_id === false) ? $this->acl_forum_id : $forum_id;
-
$is_auth = false;
eval('$is_auth = (int) (' . preg_replace(array('#acl_([a-z0-9_]+)(,\$id)?#', '#\$id#', '#aclf_([a-z0-9_]+)#', '#cfg_([a-z0-9_]+)#', '#request_([a-zA-Z0-9_]+)#'), array('(int) $auth->acl_get(\'\\1\'\\2)', '(int) $forum_id', '(int) $auth->acl_getf_global(\'\\1\')', '(int) $config[\'\\1\']', '$request->variable(\'\\1\', false)'), $module_auth) . ');');
@@ -923,6 +935,6 @@ class p_master
*/
protected function is_full_class($basename)
{
- return (substr($basename, 0, 6) === 'phpbb_' || substr($basename, 0, strlen($this->p_class) + 1) === $this->p_class . '_');
+ return (preg_match('/^(phpbb|ucp|mcp|acp)_/', $basename));
}
}
diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php
index 104fc841b6..f77f54679f 100644
--- a/phpBB/includes/functions_posting.php
+++ b/phpBB/includes/functions_posting.php
@@ -496,7 +496,14 @@ function upload_attachment($form_name, $forum_id, $local = false, $local_storage
{
if ($free_space <= $file->get('filesize'))
{
- $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED'];
+ if ($auth->acl_get('a_'))
+ {
+ $filedata['error'][] = $user->lang['ATTACH_DISK_FULL'];
+ }
+ else
+ {
+ $filedata['error'][] = $user->lang['ATTACH_QUOTA_REACHED'];
+ }
$filedata['post_attach'] = false;
$file->remove();
@@ -1180,36 +1187,32 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id
$topic_title = ($topic_notification) ? $topic_title : $subject;
$topic_title = censor_text($topic_title);
- // Get banned User ID's
- $sql = 'SELECT ban_userid
- FROM ' . BANLIST_TABLE . '
- WHERE ban_userid <> 0
- AND ban_exclude <> 1';
- $result = $db->sql_query($sql);
-
- $sql_ignore_users = ANONYMOUS . ', ' . $user->data['user_id'];
- while ($row = $db->sql_fetchrow($result))
+ // Exclude guests, current user and banned users from notifications
+ if (!function_exists('phpbb_get_banned_user_ids'))
{
- $sql_ignore_users .= ', ' . (int) $row['ban_userid'];
+ include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
}
- $db->sql_freeresult($result);
+ $sql_ignore_users = phpbb_get_banned_user_ids();
+ $sql_ignore_users[ANONYMOUS] = ANONYMOUS;
+ $sql_ignore_users[$user->data['user_id']] = $user->data['user_id'];
$notify_rows = array();
// -- get forum_userids || topic_userids
$sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber
FROM ' . (($topic_notification) ? TOPICS_WATCH_TABLE : FORUMS_WATCH_TABLE) . ' w, ' . USERS_TABLE . ' u
- WHERE w.' . (($topic_notification) ? 'topic_id' : 'forum_id') . ' = ' . (($topic_notification) ? $topic_id : $forum_id) . "
- AND w.user_id NOT IN ($sql_ignore_users)
- AND w.notify_status = " . NOTIFY_YES . '
+ WHERE w.' . (($topic_notification) ? 'topic_id' : 'forum_id') . ' = ' . (($topic_notification) ? $topic_id : $forum_id) . '
+ AND ' . $db->sql_in_set('w.user_id', $sql_ignore_users, true) . '
+ AND w.notify_status = ' . NOTIFY_YES . '
AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')
AND u.user_id = w.user_id';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
- $notify_rows[$row['user_id']] = array(
- 'user_id' => $row['user_id'],
+ $notify_user_id = (int) $row['user_id'];
+ $notify_rows[$notify_user_id] = array(
+ 'user_id' => $notify_user_id,
'username' => $row['username'],
'user_email' => $row['user_email'],
'user_jabber' => $row['user_jabber'],
@@ -1219,30 +1222,29 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id
'method' => $row['user_notify_type'],
'allowed' => false
);
+
+ // Add users who have been already notified to ignore list
+ $sql_ignore_users[$notify_user_id] = $notify_user_id;
}
$db->sql_freeresult($result);
// forum notification is sent to those not already receiving topic notifications
if ($topic_notification)
{
- if (sizeof($notify_rows))
- {
- $sql_ignore_users .= ', ' . implode(', ', array_keys($notify_rows));
- }
-
$sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber
FROM ' . FORUMS_WATCH_TABLE . ' fw, ' . USERS_TABLE . " u
WHERE fw.forum_id = $forum_id
- AND fw.user_id NOT IN ($sql_ignore_users)
- AND fw.notify_status = " . NOTIFY_YES . '
+ AND " . $db->sql_in_set('fw.user_id', $sql_ignore_users, true) . '
+ AND fw.notify_status = ' . NOTIFY_YES . '
AND u.user_type IN (' . USER_NORMAL . ', ' . USER_FOUNDER . ')
AND u.user_id = fw.user_id';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
- $notify_rows[$row['user_id']] = array(
- 'user_id' => $row['user_id'],
+ $notify_user_id = (int) $row['user_id'];
+ $notify_rows[$notify_user_id] = array(
+ 'user_id' => $notify_user_id,
'username' => $row['username'],
'user_email' => $row['user_email'],
'user_jabber' => $row['user_jabber'],
@@ -1273,7 +1275,6 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id
}
}
-
// Now, we have to do a little step before really sending, we need to distinguish our users a little bit. ;)
$msg_users = $delete_ids = $update_notification = array();
foreach ($notify_rows as $user_id => $row)
@@ -1286,6 +1287,20 @@ function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id
{
$msg_users[] = $row;
$update_notification[$row['notify_type']][] = $row['user_id'];
+
+ /*
+ * We also update the forums watch table for this user when we are
+ * sending out a topic notification to prevent sending out another
+ * notification in case this user is also subscribed to the forum
+ * this topic was posted in.
+ * Since an UPDATE query is used, this has no effect on users only
+ * subscribed to the topic (i.e. no row is created) and should not
+ * be a performance issue.
+ */
+ if ($row['notify_type'] === 'topic')
+ {
+ $update_notification['forum'][] = $row['user_id'];
+ }
}
}
unset($notify_rows);
diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php
index 91e453b8e0..434349714b 100644
--- a/phpBB/includes/functions_privmsgs.php
+++ b/phpBB/includes/functions_privmsgs.php
@@ -343,7 +343,7 @@ function check_rule(&$rules, &$rule_row, &$message_row, $user_id)
$userdata = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
- $auth2 = new auth();
+ $auth2 = new phpbb_auth();
$auth2->acl($userdata);
if (!$auth2->acl_get('a_') && !$auth2->acl_get('m_') && !$auth2->acl_getf_global('m_'))
@@ -1666,6 +1666,7 @@ function pm_notification($mode, $author, $recipients, $subject, $message, $msg_i
$subject = censor_text($subject);
+ // Exclude guests, current user and banned users from notifications
unset($recipients[ANONYMOUS], $recipients[$user->data['user_id']]);
if (!sizeof($recipients))
@@ -1673,18 +1674,12 @@ function pm_notification($mode, $author, $recipients, $subject, $message, $msg_i
return;
}
- // Get banned User ID's
- $sql = 'SELECT ban_userid
- FROM ' . BANLIST_TABLE . '
- WHERE ' . $db->sql_in_set('ban_userid', array_map('intval', array_keys($recipients))) . '
- AND ban_exclude = 0';
- $result = $db->sql_query($sql);
-
- while ($row = $db->sql_fetchrow($result))
+ if (!function_exists('phpbb_get_banned_user_ids'))
{
- unset($recipients[$row['ban_userid']]);
+ include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
}
- $db->sql_freeresult($result);
+ $banned_users = phpbb_get_banned_user_ids(array_keys($recipients));
+ $recipients = array_diff(array_keys($recipients), $banned_users);
if (!sizeof($recipients))
{
@@ -1693,7 +1688,7 @@ function pm_notification($mode, $author, $recipients, $subject, $message, $msg_i
$sql = 'SELECT user_id, username, user_email, user_lang, user_notify_pm, user_notify_type, user_jabber
FROM ' . USERS_TABLE . '
- WHERE ' . $db->sql_in_set('user_id', array_map('intval', array_keys($recipients)));
+ WHERE ' . $db->sql_in_set('user_id', $recipients);
$result = $db->sql_query($sql);
$msg_list_ary = array();
diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php
index 26c4283f67..3399334f94 100644
--- a/phpBB/includes/functions_profile_fields.php
+++ b/phpBB/includes/functions_profile_fields.php
@@ -555,7 +555,7 @@ class custom_profile
{
global $user;
// Date should display as the same date for every user regardless of timezone, so remove offset
- // to compensate for the offset added by user::format_date()
+ // to compensate for the offset added by phpbb_user::format_date()
return $user->format_date(gmmktime(0, 0, 0, $month, $day, $year) - ($user->timezone + $user->dst), $user->lang['DATE_FORMAT'], true);
}
@@ -570,7 +570,12 @@ class custom_profile
$this->get_option_lang($field_id, $lang_id, FIELD_DROPDOWN, false);
}
- if ($value == $ident_ary['data']['field_novalue'])
+ // If a dropdown field is required, users
+ // cannot choose the "no value" option.
+ // They must choose one of the other options.
+ // Therefore, here we treat a value equal to
+ // the "no value" as a lack of value, i.e. NULL.
+ if ($value == $ident_ary['data']['field_novalue'] && $ident_ary['data']['field_required'])
{
return NULL;
}
@@ -625,10 +630,10 @@ class custom_profile
$profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident'];
$user_ident = $profile_row['field_ident'];
- // checkbox - only testing for isset
+ // checkbox - set the value to "true" if it has been set to 1
if ($profile_row['field_type'] == FIELD_BOOL && $profile_row['field_length'] == 2)
{
- $value = (isset($_REQUEST[$profile_row['field_ident']])) ? true : ((!isset($user->profile_fields[$user_ident]) || $preview) ? $default_value : $user->profile_fields[$user_ident]);
+ $value = (isset($_REQUEST[$profile_row['field_ident']]) && request_var($profile_row['field_ident'], $default_value) == 1) ? true : ((!isset($user->profile_fields[$user_ident]) || $preview) ? $default_value : $user->profile_fields[$user_ident]);
}
else if ($profile_row['field_type'] == FIELD_INT)
{
diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php
index 509e1a953c..18452c27e9 100644
--- a/phpBB/includes/functions_user.php
+++ b/phpBB/includes/functions_user.php
@@ -3691,3 +3691,36 @@ function remove_newly_registered($user_id, $user_data = false)
return $user_data['group_id'];
}
+
+/**
+* Gets user ids of currently banned registered users.
+*
+* @param array $user_ids Array of users' ids to check for banning,
+* leave empty to get complete list of banned ids
+* @return array Array of banned users' ids if any, empty array otherwise
+*/
+function phpbb_get_banned_user_ids($user_ids = array())
+{
+ global $db;
+
+ $sql_user_ids = (!empty($user_ids)) ? $db->sql_in_set('ban_userid', $user_ids) : 'ban_userid <> 0';
+
+ // Get banned User ID's
+ // Ignore stale bans which were not wiped yet
+ $banned_ids_list = array();
+ $sql = 'SELECT ban_userid
+ FROM ' . BANLIST_TABLE . "
+ WHERE $sql_user_ids
+ AND ban_exclude <> 1
+ AND (ban_end > " . time() . '
+ OR ban_end = 0)';
+ $result = $db->sql_query($sql);
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $user_id = (int) $row['ban_userid'];
+ $banned_ids_list[$user_id] = $user_id;
+ }
+ $db->sql_freeresult($result);
+
+ return $banned_ids_list;
+}
diff --git a/phpBB/includes/json_response.php b/phpBB/includes/json_response.php
new file mode 100644
index 0000000000..5dd904da09
--- /dev/null
+++ b/phpBB/includes/json_response.php
@@ -0,0 +1,41 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-license.php GNU Public License
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* JSON class
+* @package phpBB3
+*/
+class phpbb_json_response
+{
+ /**
+ * Send the data to the client and exit the script.
+ *
+ * @param array $data Any additional data to send.
+ * @param bool $exit Will exit the script if true.
+ */
+ public function send($data, $exit = true)
+ {
+ header('Content-Type: application/json');
+ echo json_encode($data);
+
+ if ($exit)
+ {
+ garbage_collection();
+ exit_handler();
+ }
+ }
+}
diff --git a/phpBB/includes/mcp/mcp_main.php b/phpBB/includes/mcp/mcp_main.php
index 10e5956fc2..a21c67924d 100644
--- a/phpBB/includes/mcp/mcp_main.php
+++ b/phpBB/includes/mcp/mcp_main.php
@@ -907,16 +907,11 @@ function mcp_fork_topic($topic_ids)
if (!isset($search_type) && $topic_row['enable_indexing'])
{
// Select the search method and do some additional checks to ensure it can actually be utilised
- $search_type = basename($config['search_type']);
-
- if (!file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx))
- {
- trigger_error('NO_SUCH_SEARCH_MODULE');
- }
+ $search_type = $config['search_type'];
if (!class_exists($search_type))
{
- include("{$phpbb_root_path}includes/search/$search_type.$phpEx");
+ trigger_error('NO_SUCH_SEARCH_MODULE');
}
$error = false;
diff --git a/phpBB/includes/mcp/mcp_post.php b/phpBB/includes/mcp/mcp_post.php
index ee79928eb1..2a52a858b3 100644
--- a/phpBB/includes/mcp/mcp_post.php
+++ b/phpBB/includes/mcp/mcp_post.php
@@ -464,12 +464,10 @@ function change_poster(&$post_info, $userdata)
}
// refresh search cache of this post
- $search_type = basename($config['search_type']);
+ $search_type = $config['search_type'];
- if (file_exists($phpbb_root_path . 'includes/search/' . $search_type . '.' . $phpEx))
+ if (class_exists($search_type))
{
- require("{$phpbb_root_path}includes/search/$search_type.$phpEx");
-
// We do some additional checks in the module to ensure it can actually be utilised
$error = false;
$search = new $search_type($error);
diff --git a/phpBB/includes/mcp/mcp_queue.php b/phpBB/includes/mcp/mcp_queue.php
index ef32b5f03c..59fa8b7263 100644
--- a/phpBB/includes/mcp/mcp_queue.php
+++ b/phpBB/includes/mcp/mcp_queue.php
@@ -451,6 +451,7 @@ function approve_post($post_id_list, $id, $mode)
{
global $db, $template, $user, $config;
global $phpEx, $phpbb_root_path;
+ global $request;
if (!check_ids($post_id_list, POSTS_TABLE, 'post_id', array('m_approve')))
{
@@ -709,7 +710,20 @@ function approve_post($post_id_list, $id, $mode)
$add_message = '<br /><br />' . sprintf($user->lang['RETURN_POST'], '<a href="' . $post_url . '">', '</a>');
}
- trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>') . $add_message);
+ $message = $user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>') . $add_message;
+
+ if ($request->is_ajax())
+ {
+ $json_response = new phpbb_json_response;
+ $json_response->send(array(
+ 'MESSAGE_TITLE' => $user->lang['INFORMATION'],
+ 'MESSAGE_TEXT' => $message,
+ 'REFRESH_DATA' => null,
+ 'approved' => true
+ ));
+ }
+
+ trigger_error($message);
}
}
@@ -968,7 +982,20 @@ function disapprove_post($post_id_list, $id, $mode)
}
else
{
+ $message = $user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>');
+
+ if ($request->is_ajax())
+ {
+ $json_response = new phpbb_json_response;
+ $json_response->send(array(
+ 'MESSAGE_TITLE' => $user->lang['INFORMATION'],
+ 'MESSAGE_TEXT' => $message,
+ 'REFRESH_DATA' => null,
+ 'approved' => false
+ ));
+ }
+
meta_refresh(3, $redirect);
- trigger_error($user->lang[$success_msg] . '<br /><br />' . sprintf($user->lang['RETURN_PAGE'], "<a href=\"$redirect\">", '</a>'));
+ trigger_error($message);
}
}
diff --git a/phpBB/includes/mcp/mcp_reports.php b/phpBB/includes/mcp/mcp_reports.php
index 95e84e816b..69c6a4cfff 100644
--- a/phpBB/includes/mcp/mcp_reports.php
+++ b/phpBB/includes/mcp/mcp_reports.php
@@ -71,7 +71,7 @@ class mcp_reports
// closed reports are accessed by report id
$report_id = request_var('r', 0);
- $sql = 'SELECT r.post_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour
+ $sql = 'SELECT r.post_id, r.user_id, r.report_id, r.report_closed, report_time, r.report_text, r.reported_post_text, rr.reason_title, rr.reason_description, u.username, u.username_clean, u.user_colour
FROM ' . REPORTS_TABLE . ' r, ' . REPORTS_REASONS_TABLE . ' rr, ' . USERS_TABLE . ' u
WHERE ' . (($report_id) ? 'r.report_id = ' . $report_id : "r.post_id = $post_id") . '
AND rr.reason_id = r.reason_id
@@ -116,8 +116,9 @@ class mcp_reports
$template->assign_vars(array(
'S_TOPIC_REVIEW' => true,
'S_BBCODE_ALLOWED' => $post_info['enable_bbcode'],
- 'TOPIC_TITLE' => $post_info['topic_title'])
- );
+ 'TOPIC_TITLE' => $post_info['topic_title'],
+ 'REPORTED_POST_ID' => $post_id,
+ ));
}
$topic_tracking_info = $extensions = $attachments = array();
@@ -226,7 +227,7 @@ class mcp_reports
'REPORTER_NAME' => get_username_string('username', $report['user_id'], $report['username'], $report['user_colour']),
'U_VIEW_REPORTER_PROFILE' => get_username_string('profile', $report['user_id'], $report['username'], $report['user_colour']),
- 'POST_PREVIEW' => $message,
+ 'POST_PREVIEW' => bbcode_nl2br($report['reported_post_text']),
'POST_SUBJECT' => ($post_info['post_subject']) ? $post_info['post_subject'] : $user->lang['NO_SUBJECT'],
'POST_DATE' => $user->format_date($post_info['post_time']),
'POST_IP' => $post_info['poster_ip'],
diff --git a/phpBB/includes/mcp/mcp_topic.php b/phpBB/includes/mcp/mcp_topic.php
index 598b470663..d4ba89b04c 100644
--- a/phpBB/includes/mcp/mcp_topic.php
+++ b/phpBB/includes/mcp/mcp_topic.php
@@ -49,6 +49,16 @@ function mcp_topic_view($id, $mode, $action)
$submitted_id_list = request_var('post_ids', array(0));
$checked_ids = $post_id_list = request_var('post_id_list', array(0));
+ // Resync Topic?
+ if ($action == 'resync')
+ {
+ if (!function_exists('mcp_resync_topics'))
+ {
+ include($phpbb_root_path . 'includes/mcp/mcp_forum.' . $phpEx);
+ }
+ mcp_resync_topics(array($topic_id));
+ }
+
// Split Topic?
if ($action == 'split_all' || $action == 'split_beyond')
{
@@ -319,6 +329,7 @@ function mcp_topic_view($id, $mode, $action)
'S_CAN_APPROVE' => ($has_unapproved_posts && $auth->acl_get('m_approve', $topic_info['forum_id'])) ? true : false,
'S_CAN_LOCK' => ($auth->acl_get('m_lock', $topic_info['forum_id'])) ? true : false,
'S_CAN_REPORT' => ($auth->acl_get('m_report', $topic_info['forum_id'])) ? true : false,
+ 'S_CAN_SYNC' => $auth->acl_get('m_', $topic_info['forum_id']),
'S_REPORT_VIEW' => ($action == 'reports') ? true : false,
'S_MERGE_VIEW' => ($action == 'merge') ? true : false,
'S_SPLIT_VIEW' => ($action == 'split') ? true : false,
diff --git a/phpBB/includes/mcp/mcp_warn.php b/phpBB/includes/mcp/mcp_warn.php
index d8e655000f..9d838790a0 100644
--- a/phpBB/includes/mcp/mcp_warn.php
+++ b/phpBB/includes/mcp/mcp_warn.php
@@ -251,7 +251,7 @@ class mcp_warn
// Check if can send a notification
if ($config['allow_privmsg'])
{
- $auth2 = new auth();
+ $auth2 = new phpbb_auth();
$auth2->acl($user_row);
$s_can_notify = ($auth2->acl_get('u_readpm')) ? true : false;
unset($auth2);
@@ -374,7 +374,7 @@ class mcp_warn
// Check if can send a notification
if ($config['allow_privmsg'])
{
- $auth2 = new auth();
+ $auth2 = new phpbb_auth();
$auth2->acl($user_row);
$s_can_notify = ($auth2->acl_get('u_readpm')) ? true : false;
unset($auth2);
diff --git a/phpBB/includes/request/type_cast_helper.php b/phpBB/includes/request/type_cast_helper.php
index 5aa0372328..561e8fc251 100644
--- a/phpBB/includes/request/type_cast_helper.php
+++ b/phpBB/includes/request/type_cast_helper.php
@@ -34,7 +34,7 @@ class phpbb_request_type_cast_helper implements phpbb_request_type_cast_helper_i
*/
public function __construct()
{
- if (version_compare(PHP_VERSION, '6.0.0-dev', '>='))
+ if (version_compare(PHP_VERSION, '5.4.0-dev', '>='))
{
$this->strip = false;
}
diff --git a/phpBB/includes/search/base.php b/phpBB/includes/search/base.php
index f691bc942f..b364dead9a 100644
--- a/phpBB/includes/search/base.php
+++ b/phpBB/includes/search/base.php
@@ -294,7 +294,7 @@ class phpbb_search_base
$sql_where = '';
foreach ($authors as $author)
{
- $sql_where .= (($sql_where) ? ' OR ' : '') . 'search_authors LIKE \'% ' . (int) $author . ' %\'';
+ $sql_where .= (($sql_where) ? ' OR ' : '') . 'search_authors ' . $db->sql_like_expression($db->any_char . ' ' . (int) $author . ' ' . $db->any_char);
}
$sql = 'SELECT search_key
diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php
index 5372cfac7b..7c94038cc9 100644
--- a/phpBB/includes/search/fulltext_mysql.php
+++ b/phpBB/includes/search/fulltext_mysql.php
@@ -708,7 +708,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
*/
function index_remove($post_ids, $author_ids, $forum_ids)
{
- $this->destroy_cache(array(), $author_ids);
+ $this->destroy_cache(array(), array_unique($author_ids));
}
/**
@@ -897,11 +897,7 @@ class phpbb_search_fulltext_mysql extends phpbb_search_base
}
$db->sql_freeresult($result);
- $sql = 'SELECT COUNT(post_id) as total_posts
- FROM ' . POSTS_TABLE;
- $result = $db->sql_query($sql);
- $this->stats['total_posts'] = (int) $db->sql_fetchfield('total_posts');
- $db->sql_freeresult($result);
+ $this->stats['total_posts'] = empty($this->stats) ? 0 : $db->get_estimated_row_count(POSTS_TABLE);
}
/**
diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php
index b9085695ac..3e029c86d0 100644
--- a/phpBB/includes/search/fulltext_native.php
+++ b/phpBB/includes/search/fulltext_native.php
@@ -1335,7 +1335,7 @@ class phpbb_search_fulltext_native extends phpbb_search_base
$db->sql_query($sql);
}
- $this->destroy_cache(array_unique($word_texts), $author_ids);
+ $this->destroy_cache(array_unique($word_texts), array_unique($author_ids));
}
/**
@@ -1462,17 +1462,8 @@ class phpbb_search_fulltext_native extends phpbb_search_base
{
global $db;
- $sql = 'SELECT COUNT(*) as total_words
- FROM ' . SEARCH_WORDLIST_TABLE;
- $result = $db->sql_query($sql);
- $this->stats['total_words'] = (int) $db->sql_fetchfield('total_words');
- $db->sql_freeresult($result);
-
- $sql = 'SELECT COUNT(*) as total_matches
- FROM ' . SEARCH_WORDMATCH_TABLE;
- $result = $db->sql_query($sql);
- $this->stats['total_matches'] = (int) $db->sql_fetchfield('total_matches');
- $db->sql_freeresult($result);
+ $this->stats['total_words'] = $db->get_estimated_row_count(SEARCH_WORDLIST_TABLE);
+ $this->stats['total_matches'] = $db->get_estimated_row_count(SEARCH_WORDMATCH_TABLE);
}
/**
diff --git a/phpBB/includes/session.php b/phpBB/includes/session.php
index 6dad068ecb..bcdff54457 100644
--- a/phpBB/includes/session.php
+++ b/phpBB/includes/session.php
@@ -19,7 +19,7 @@ if (!defined('IN_PHPBB'))
* Session class
* @package phpBB3
*/
-class session
+class phpbb_session
{
var $cookie_data = array();
var $page = array();
@@ -1511,843 +1511,3 @@ class session
$db->sql_query($sql);
}
}
-
-
-/**
-* Base user class
-*
-* This is the overarching class which contains (through session extend)
-* all methods utilised for user functionality during a session.
-*
-* @package phpBB3
-*/
-class user extends session
-{
- var $lang = array();
- var $help = array();
- var $theme = array();
- var $date_format;
- var $timezone;
- var $dst;
-
- var $lang_name = false;
- var $lang_id = false;
- var $lang_path;
- var $img_lang;
- var $img_array = array();
-
- // Able to add new options (up to id 31)
- var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'popuppm' => 10, 'sig_bbcode' => 15, 'sig_smilies' => 16, 'sig_links' => 17);
-
- /**
- * Constructor to set the lang path
- */
- function user()
- {
- global $phpbb_root_path;
-
- $this->lang_path = $phpbb_root_path . 'language/';
- }
-
- /**
- * Function to set custom language path (able to use directory outside of phpBB)
- *
- * @param string $lang_path New language path used.
- * @access public
- */
- function set_custom_lang_path($lang_path)
- {
- $this->lang_path = $lang_path;
-
- if (substr($this->lang_path, -1) != '/')
- {
- $this->lang_path .= '/';
- }
- }
-
- /**
- * Setup basic user-specific items (style, language, ...)
- */
- function setup($lang_set = false, $style = false)
- {
- global $db, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache;
-
- if ($this->data['user_id'] != ANONYMOUS)
- {
- $this->lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']);
-
- $this->date_format = $this->data['user_dateformat'];
- $this->timezone = $this->data['user_timezone'] * 3600;
- $this->dst = $this->data['user_dst'] * 3600;
- }
- else
- {
- $this->lang_name = basename($config['default_lang']);
- $this->date_format = $config['default_dateformat'];
- $this->timezone = $config['board_timezone'] * 3600;
- $this->dst = $config['board_dst'] * 3600;
-
- /**
- * If a guest user is surfing, we try to guess his/her language first by obtaining the browser language
- * If re-enabled we need to make sure only those languages installed are checked
- * Commented out so we do not loose the code.
-
- if ($request->header('Accept-Language'))
- {
- $accept_lang_ary = explode(',', $request->header('Accept-Language'));
-
- foreach ($accept_lang_ary as $accept_lang)
- {
- // Set correct format ... guess full xx_YY form
- $accept_lang = substr($accept_lang, 0, 2) . '_' . strtoupper(substr($accept_lang, 3, 2));
- $accept_lang = basename($accept_lang);
-
- if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx"))
- {
- $this->lang_name = $config['default_lang'] = $accept_lang;
- break;
- }
- else
- {
- // No match on xx_YY so try xx
- $accept_lang = substr($accept_lang, 0, 2);
- $accept_lang = basename($accept_lang);
-
- if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx"))
- {
- $this->lang_name = $config['default_lang'] = $accept_lang;
- break;
- }
- }
- }
- }
- */
- }
-
- // We include common language file here to not load it every time a custom language file is included
- $lang = &$this->lang;
-
- // Do not suppress error if in DEBUG_EXTRA mode
- $include_result = (defined('DEBUG_EXTRA')) ? (include $this->lang_path . $this->lang_name . "/common.$phpEx") : (@include $this->lang_path . $this->lang_name . "/common.$phpEx");
-
- if ($include_result === false)
- {
- die('Language file ' . $this->lang_path . $this->lang_name . "/common.$phpEx" . " couldn't be opened.");
- }
-
- $this->add_lang($lang_set);
- unset($lang_set);
-
- $style_request = request_var('style', 0);
- if ($style_request && $auth->acl_get('a_styles') && !defined('ADMIN_START'))
- {
- global $SID, $_EXTRA_URL;
-
- $style = $style_request;
- $SID .= '&amp;style=' . $style;
- $_EXTRA_URL = array('style=' . $style);
- }
- else
- {
- // Set up style
- $style = ($style) ? $style : ((!$config['override_user_style']) ? $this->data['user_style'] : $config['default_style']);
- }
-
- $sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, t.template_inherits_id, t.template_inherit_path, c.theme_path, c.theme_name, c.theme_id
- FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . " c
- WHERE s.style_id = $style
- AND t.template_id = s.template_id
- AND c.theme_id = s.theme_id";
- $result = $db->sql_query($sql, 3600);
- $this->theme = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
-
- // User has wrong style
- if (!$this->theme && $style == $this->data['user_style'])
- {
- $style = $this->data['user_style'] = $config['default_style'];
-
- $sql = 'UPDATE ' . USERS_TABLE . "
- SET user_style = $style
- WHERE user_id = {$this->data['user_id']}";
- $db->sql_query($sql);
-
- $sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, c.theme_path, c.theme_name, c.theme_id
- FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . " c
- WHERE s.style_id = $style
- AND t.template_id = s.template_id
- AND c.theme_id = s.theme_id";
- $result = $db->sql_query($sql, 3600);
- $this->theme = $db->sql_fetchrow($result);
- $db->sql_freeresult($result);
- }
-
- if (!$this->theme)
- {
- trigger_error('Could not get style data', E_USER_ERROR);
- }
-
- // Now parse the cfg file and cache it
- $parsed_items = $cache->obtain_cfg_items($this->theme);
-
- // We are only interested in the theme configuration for now
- $parsed_items = $parsed_items['theme'];
-
- $check_for = array(
- 'pagination_sep' => (string) ', '
- );
-
- foreach ($check_for as $key => $default_value)
- {
- $this->theme[$key] = (isset($parsed_items[$key])) ? $parsed_items[$key] : $default_value;
- settype($this->theme[$key], gettype($default_value));
-
- if (is_string($default_value))
- {
- $this->theme[$key] = htmlspecialchars($this->theme[$key]);
- }
- }
-
- $template->set_template();
-
- $this->img_lang = $this->lang_name;
-
- // Call phpbb_user_session_handler() in case external application want to "bend" some variables or replace classes...
- // After calling it we continue script execution...
- phpbb_user_session_handler();
-
- // If this function got called from the error handler we are finished here.
- if (defined('IN_ERROR_HANDLER'))
- {
- return;
- }
-
- // Disable board if the install/ directory is still present
- // For the brave development army we do not care about this, else we need to comment out this everytime we develop locally
- if (!defined('DEBUG_EXTRA') && !defined('ADMIN_START') && !defined('IN_INSTALL') && !defined('IN_LOGIN') && file_exists($phpbb_root_path . 'install') && !is_file($phpbb_root_path . 'install'))
- {
- // Adjust the message slightly according to the permissions
- if ($auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))
- {
- $message = 'REMOVE_INSTALL';
- }
- else
- {
- $message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE';
- }
- trigger_error($message);
- }
-
- // Is board disabled and user not an admin or moderator?
- if ($config['board_disable'] && !defined('IN_LOGIN') && !$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_'))
- {
- if ($this->data['is_bot'])
- {
- send_status_line(503, 'Service Unavailable');
- }
-
- $message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE';
- trigger_error($message);
- }
-
- // Is load exceeded?
- if ($config['limit_load'] && $this->load !== false)
- {
- if ($this->load > floatval($config['limit_load']) && !defined('IN_LOGIN') && !defined('IN_ADMIN'))
- {
- // Set board disabled to true to let the admins/mods get the proper notification
- $config['board_disable'] = '1';
-
- if (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_'))
- {
- if ($this->data['is_bot'])
- {
- send_status_line(503, 'Service Unavailable');
- }
- trigger_error('BOARD_UNAVAILABLE');
- }
- }
- }
-
- if (isset($this->data['session_viewonline']))
- {
- // Make sure the user is able to hide his session
- if (!$this->data['session_viewonline'])
- {
- // Reset online status if not allowed to hide the session...
- if (!$auth->acl_get('u_hideonline'))
- {
- $sql = 'UPDATE ' . SESSIONS_TABLE . '
- SET session_viewonline = 1
- WHERE session_user_id = ' . $this->data['user_id'];
- $db->sql_query($sql);
- $this->data['session_viewonline'] = 1;
- }
- }
- else if (!$this->data['user_allow_viewonline'])
- {
- // the user wants to hide and is allowed to -> cloaking device on.
- if ($auth->acl_get('u_hideonline'))
- {
- $sql = 'UPDATE ' . SESSIONS_TABLE . '
- SET session_viewonline = 0
- WHERE session_user_id = ' . $this->data['user_id'];
- $db->sql_query($sql);
- $this->data['session_viewonline'] = 0;
- }
- }
- }
-
-
- // Does the user need to change their password? If so, redirect to the
- // ucp profile reg_details page ... of course do not redirect if we're already in the ucp
- if (!defined('IN_ADMIN') && !defined('ADMIN_START') && $config['chg_passforce'] && !empty($this->data['is_registered']) && $auth->acl_get('u_chgpasswd') && $this->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400))
- {
- if (strpos($this->page['query_string'], 'mode=reg_details') === false && $this->page['page_name'] != "ucp.$phpEx")
- {
- redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=profile&amp;mode=reg_details'));
- }
- }
-
- return;
- }
-
- /**
- * More advanced language substitution
- * Function to mimic sprintf() with the possibility of using phpBB's language system to substitute nullar/singular/plural forms.
- * Params are the language key and the parameters to be substituted.
- * This function/functionality is inspired by SHS` and Ashe.
- *
- * Example call: <samp>$user->lang('NUM_POSTS_IN_QUEUE', 1);</samp>
- *
- * If the first parameter is an array, the elements are used as keys and subkeys to get the language entry:
- * Example: <samp>$user->lang(array('datetime', 'AGO'), 1)</samp> uses $user->lang['datetime']['AGO'] as language entry.
- */
- function lang()
- {
- $args = func_get_args();
- $key = $args[0];
-
- if (is_array($key))
- {
- $lang = &$this->lang[array_shift($key)];
-
- foreach ($key as $_key)
- {
- $lang = &$lang[$_key];
- }
- }
- else
- {
- $lang = &$this->lang[$key];
- }
-
- // Return if language string does not exist
- if (!isset($lang) || (!is_string($lang) && !is_array($lang)))
- {
- return $key;
- }
-
- // If the language entry is a string, we simply mimic sprintf() behaviour
- if (is_string($lang))
- {
- if (sizeof($args) == 1)
- {
- return $lang;
- }
-
- // Replace key with language entry and simply pass along...
- $args[0] = $lang;
- return call_user_func_array('sprintf', $args);
- }
- else if (sizeof($lang) == 0)
- {
- // If the language entry is an empty array, we just return the language key
- return $args[0];
- }
-
- // It is an array... now handle different nullar/singular/plural forms
- $key_found = false;
-
- // We now get the first number passed and will select the key based upon this number
- for ($i = 1, $num_args = sizeof($args); $i < $num_args; $i++)
- {
- if (is_int($args[$i]) || is_float($args[$i]))
- {
- if ($args[$i] == 0 && isset($lang[0]))
- {
- // We allow each translation using plural forms to specify a version for the case of 0 things,
- // so that "0 users" may be displayed as "No users".
- $key_found = 0;
- break;
- }
- else
- {
- $use_plural_form = $this->get_plural_form($args[$i]);
- if (isset($lang[$use_plural_form]))
- {
- // The key we should use exists, so we use it.
- $key_found = $use_plural_form;
- }
- else
- {
- // If the key we need to use does not exist, we fall back to the previous one.
- $numbers = array_keys($lang);
-
- foreach ($numbers as $num)
- {
- if ($num > $use_plural_form)
- {
- break;
- }
-
- $key_found = $num;
- }
- }
- break;
- }
- }
- }
-
- // Ok, let's check if the key was found, else use the last entry (because it is mostly the plural form)
- if ($key_found === false)
- {
- $numbers = array_keys($lang);
- $key_found = end($numbers);
- }
-
- // Use the language string we determined and pass it to sprintf()
- $args[0] = $lang[$key_found];
- return call_user_func_array('sprintf', $args);
- }
-
- /**
- * Determine which plural form we should use.
- * For some languages this is not as simple as for English.
- *
- * @param $number int|float The number we want to get the plural case for. Float numbers are floored.
- * @param $force_rule mixed False to use the plural rule of the language package
- * or an integer to force a certain plural rule
- * @return int The plural-case we need to use for the number plural-rule combination
- */
- function get_plural_form($number, $force_rule = false)
- {
- $number = (int) $number;
-
- // Default to English system
- $plural_rule = ($force_rule !== false) ? $force_rule : ((isset($this->lang['PLURAL_RULE'])) ? $this->lang['PLURAL_RULE'] : 1);
-
- return phpbb_get_plural_form($plural_rule, $number);
- }
-
- /**
- * Add Language Items - use_db and use_help are assigned where needed (only use them to force inclusion)
- *
- * @param mixed $lang_set specifies the language entries to include
- * @param bool $use_db internal variable for recursion, do not use
- * @param bool $use_help internal variable for recursion, do not use
- * @param string $ext_name The extension to load language from, or empty for core files
- *
- * Examples:
- * <code>
- * $lang_set = array('posting', 'help' => 'faq');
- * $lang_set = array('posting', 'viewtopic', 'help' => array('bbcode', 'faq'))
- * $lang_set = array(array('posting', 'viewtopic'), 'help' => array('bbcode', 'faq'))
- * $lang_set = 'posting'
- * $lang_set = array('help' => 'faq', 'db' => array('help:faq', 'posting'))
- * </code>
- */
- function add_lang($lang_set, $use_db = false, $use_help = false, $ext_name = '')
- {
- global $phpEx;
-
- if (is_array($lang_set))
- {
- foreach ($lang_set as $key => $lang_file)
- {
- // Please do not delete this line.
- // We have to force the type here, else [array] language inclusion will not work
- $key = (string) $key;
-
- if ($key == 'db')
- {
- $this->add_lang($lang_file, true, $use_help, $ext_name);
- }
- else if ($key == 'help')
- {
- $this->add_lang($lang_file, $use_db, true, $ext_name);
- }
- else if (!is_array($lang_file))
- {
- $this->set_lang($this->lang, $this->help, $lang_file, $use_db, $use_help, $ext_name);
- }
- else
- {
- $this->add_lang($lang_file, $use_db, $use_help, $ext_name);
- }
- }
- unset($lang_set);
- }
- else if ($lang_set)
- {
- $this->set_lang($this->lang, $this->help, $lang_set, $use_db, $use_help, $ext_name);
- }
- }
-
- /**
- * Add Language Items from an extension - use_db and use_help are assigned where needed (only use them to force inclusion)
- *
- * @param string $ext_name The extension to load language from, or empty for core files
- * @param mixed $lang_set specifies the language entries to include
- * @param bool $use_db internal variable for recursion, do not use
- * @param bool $use_help internal variable for recursion, do not use
- */
- function add_lang_ext($ext_name, $lang_set, $use_db = false, $use_help = false)
- {
- if ($ext_name === '/')
- {
- $ext_name = '';
- }
-
- $this->add_lang($lang_set, $use_db, $use_help, $ext_name);
- }
-
- /**
- * Set language entry (called by add_lang)
- * @access private
- */
- function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false, $ext_name = '')
- {
- global $phpbb_root_path, $phpEx;
-
- // Make sure the language name is set (if the user setup did not happen it is not set)
- if (!$this->lang_name)
- {
- global $config;
- $this->lang_name = basename($config['default_lang']);
- }
-
- // $lang == $this->lang
- // $help == $this->help
- // - add appropriate variables here, name them as they are used within the language file...
- if (!$use_db)
- {
- if ($use_help && strpos($lang_file, '/') !== false)
- {
- $filename = dirname($lang_file) . '/help_' . basename($lang_file);
- }
- else
- {
- $filename = (($use_help) ? 'help_' : '') . $lang_file;
- }
-
- if ($ext_name)
- {
- global $phpbb_extension_manager;
- $ext_path = $phpbb_extension_manager->get_extension_path($ext_name, true);
-
- $lang_path = $ext_path . 'language/';
- }
- else
- {
- $lang_path = $this->lang_path;
- }
-
- if (strpos($phpbb_root_path . $filename, $lang_path . $this->lang_name . '/') === 0)
- {
- $language_filename = $phpbb_root_path . $filename;
- }
- else
- {
- $language_filename = $lang_path . $this->lang_name . '/' . $filename . '.' . $phpEx;
- }
-
- if (!file_exists($language_filename))
- {
- global $config;
-
- if ($this->lang_name == 'en')
- {
- // The user's selected language is missing the file, the board default's language is missing the file, and the file doesn't exist in /en.
- $language_filename = str_replace($lang_path . 'en', $lang_path . $this->data['user_lang'], $language_filename);
- trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR);
- }
- else if ($this->lang_name == basename($config['default_lang']))
- {
- // Fall back to the English Language
- $this->lang_name = 'en';
- $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name);
- }
- else if ($this->lang_name == $this->data['user_lang'])
- {
- // Fall back to the board default language
- $this->lang_name = basename($config['default_lang']);
- $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name);
- }
-
- // Reset the lang name
- $this->lang_name = (file_exists($lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']);
- return;
- }
-
- // Do not suppress error if in DEBUG_EXTRA mode
- $include_result = (defined('DEBUG_EXTRA')) ? (include $language_filename) : (@include $language_filename);
-
- if ($include_result === false)
- {
- trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR);
- }
- }
- else if ($use_db)
- {
- // Get Database Language Strings
- // Put them into $lang if nothing is prefixed, put them into $help if help: is prefixed
- // For example: help:faq, posting
- }
- }
-
- /**
- * Format user date
- *
- * @param int $gmepoch unix timestamp
- * @param string $format date format in date() notation. | used to indicate relative dates, for example |d m Y|, h:i is translated to Today, h:i.
- * @param bool $forcedate force non-relative date format.
- *
- * @return mixed translated date
- */
- function format_date($gmepoch, $format = false, $forcedate = false)
- {
- static $midnight;
- static $date_cache;
-
- $format = (!$format) ? $this->date_format : $format;
- $now = time();
- $delta = $now - $gmepoch;
-
- if (!isset($date_cache[$format]))
- {
- // Is the user requesting a friendly date format (i.e. 'Today 12:42')?
- $date_cache[$format] = array(
- 'is_short' => strpos($format, '|'),
- 'format_short' => substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1),
- 'format_long' => str_replace('|', '', $format),
- 'lang' => $this->lang['datetime'],
- );
-
- // Short representation of month in format? Some languages use different terms for the long and short format of May
- if ((strpos($format, '\M') === false && strpos($format, 'M') !== false) || (strpos($format, '\r') === false && strpos($format, 'r') !== false))
- {
- $date_cache[$format]['lang']['May'] = $this->lang['datetime']['May_short'];
- }
- }
-
- // Zone offset
- $zone_offset = $this->timezone + $this->dst;
-
- // Show date < 1 hour ago as 'xx min ago' but not greater than 60 seconds in the future
- // A small tolerence is given for times in the future but in the same minute are displayed as '< than a minute ago'
- if ($delta < 3600 && $delta > -60 && ($delta >= -5 || (($now / 60) % 60) == (($gmepoch / 60) % 60)) && $date_cache[$format]['is_short'] !== false && !$forcedate && isset($this->lang['datetime']['AGO']))
- {
- return $this->lang(array('datetime', 'AGO'), max(0, (int) floor($delta / 60)));
- }
-
- if (!$midnight)
- {
- list($d, $m, $y) = explode(' ', gmdate('j n Y', time() + $zone_offset));
- $midnight = gmmktime(0, 0, 0, $m, $d, $y) - $zone_offset;
- }
-
- if ($date_cache[$format]['is_short'] !== false && !$forcedate && !($gmepoch < $midnight - 86400 || $gmepoch > $midnight + 172800))
- {
- $day = false;
-
- if ($gmepoch > $midnight + 86400)
- {
- $day = 'TOMORROW';
- }
- else if ($gmepoch > $midnight)
- {
- $day = 'TODAY';
- }
- else if ($gmepoch > $midnight - 86400)
- {
- $day = 'YESTERDAY';
- }
-
- if ($day !== false)
- {
- return str_replace('||', $this->lang['datetime'][$day], strtr(@gmdate($date_cache[$format]['format_short'], $gmepoch + $zone_offset), $date_cache[$format]['lang']));
- }
- }
-
- return strtr(@gmdate($date_cache[$format]['format_long'], $gmepoch + $zone_offset), $date_cache[$format]['lang']);
- }
-
- /**
- * Get language id currently used by the user
- */
- function get_iso_lang_id()
- {
- global $config, $db;
-
- if (!empty($this->lang_id))
- {
- return $this->lang_id;
- }
-
- if (!$this->lang_name)
- {
- $this->lang_name = $config['default_lang'];
- }
-
- $sql = 'SELECT lang_id
- FROM ' . LANG_TABLE . "
- WHERE lang_iso = '" . $db->sql_escape($this->lang_name) . "'";
- $result = $db->sql_query($sql);
- $this->lang_id = (int) $db->sql_fetchfield('lang_id');
- $db->sql_freeresult($result);
-
- return $this->lang_id;
- }
-
- /**
- * Get users profile fields
- */
- function get_profile_fields($user_id)
- {
- global $db;
-
- if (isset($this->profile_fields))
- {
- return;
- }
-
- $sql = 'SELECT *
- FROM ' . PROFILE_FIELDS_DATA_TABLE . "
- WHERE user_id = $user_id";
- $result = $db->sql_query_limit($sql, 1);
- $this->profile_fields = (!($row = $db->sql_fetchrow($result))) ? array() : $row;
- $db->sql_freeresult($result);
- }
-
- /**
- * Specify/Get image
- */
- function img($img, $alt = '')
- {
- $alt = (!empty($this->lang[$alt])) ? $this->lang[$alt] : $alt;
- return '<span class="imageset ' . $img . '">' . $alt . '</span>';
- }
-
- /**
- * Get option bit field from user options.
- *
- * @param int $key option key, as defined in $keyoptions property.
- * @param int $data bit field value to use, or false to use $this->data['user_options']
- * @return bool true if the option is set in the bit field, false otherwise
- */
- function optionget($key, $data = false)
- {
- $var = ($data !== false) ? $data : $this->data['user_options'];
- return phpbb_optionget($this->keyoptions[$key], $var);
- }
-
- /**
- * Set option bit field for user options.
- *
- * @param int $key Option key, as defined in $keyoptions property.
- * @param bool $value True to set the option, false to clear the option.
- * @param int $data Current bit field value, or false to use $this->data['user_options']
- * @return int|bool If $data is false, the bit field is modified and
- * written back to $this->data['user_options'], and
- * return value is true if the bit field changed and
- * false otherwise. If $data is not false, the new
- * bitfield value is returned.
- */
- function optionset($key, $value, $data = false)
- {
- $var = ($data !== false) ? $data : $this->data['user_options'];
-
- $new_var = phpbb_optionset($this->keyoptions[$key], $value, $var);
-
- if ($data === false)
- {
- if ($new_var != $var)
- {
- $this->data['user_options'] = $new_var;
- return true;
- }
- else
- {
- return false;
- }
- }
- else
- {
- return $new_var;
- }
- }
-
- /**
- * Funtion to make the user leave the NEWLY_REGISTERED system group.
- * @access public
- */
- function leave_newly_registered()
- {
- global $db;
-
- if (empty($this->data['user_new']))
- {
- return false;
- }
-
- if (!function_exists('remove_newly_registered'))
- {
- global $phpbb_root_path, $phpEx;
-
- include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
- }
- if ($group = remove_newly_registered($this->data['user_id'], $this->data))
- {
- $this->data['group_id'] = $group;
-
- }
- $this->data['user_permissions'] = '';
- $this->data['user_new'] = 0;
-
- return true;
- }
-
- /**
- * Returns all password protected forum ids the user is currently NOT authenticated for.
- *
- * @return array Array of forum ids
- * @access public
- */
- function get_passworded_forums()
- {
- global $db;
-
- $sql = 'SELECT f.forum_id, fa.user_id
- FROM ' . FORUMS_TABLE . ' f
- LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa
- ON (fa.forum_id = f.forum_id
- AND fa.session_id = '" . $db->sql_escape($this->session_id) . "')
- WHERE f.forum_password <> ''";
- $result = $db->sql_query($sql);
-
- $forum_ids = array();
- while ($row = $db->sql_fetchrow($result))
- {
- $forum_id = (int) $row['forum_id'];
-
- if ($row['user_id'] != $this->data['user_id'])
- {
- $forum_ids[$forum_id] = $forum_id;
- }
- }
- $db->sql_freeresult($result);
-
- return $forum_ids;
- }
-}
diff --git a/phpBB/includes/startup.php b/phpBB/includes/startup.php
index 2100fbd97e..f75d70e366 100644
--- a/phpBB/includes/startup.php
+++ b/phpBB/includes/startup.php
@@ -19,7 +19,8 @@ if (!defined('E_DEPRECATED'))
{
define('E_DEPRECATED', 8192);
}
-error_reporting(E_ALL & ~E_NOTICE & ~E_DEPRECATED);
+$level = E_ALL & ~E_NOTICE & ~E_DEPRECATED;
+error_reporting($level);
/*
* Remove variables created by register_globals from the global scope
@@ -146,5 +147,36 @@ if (function_exists('date_default_timezone_set') && function_exists('date_defaul
date_default_timezone_set(@date_default_timezone_get());
}
+// Autoloading of dependencies.
+// Three options are supported:
+// 1. If dependencies are installed with Composer, Composer will create a
+// vendor/.composer/autoload.php. If this file exists it will be
+// automatically used by phpBB. This is the default mode that phpBB
+// will use when shipped.
+// 2. To disable composer autoloading, PHPBB_NO_COMPOSER_AUTOLOAD can be specified.
+// Additionally specify PHPBB_AUTOLOAD=/path/to/autoload.php in the
+// environment. This is useful for running CLI scripts and tests.
+// /path/to/autoload.php should define and register class loaders
+// for all of phpBB's dependencies.
+// 3. You can also set PHPBB_NO_COMPOSER_AUTOLOAD without setting PHPBB_AUTOLOAD.
+// In this case autoloading needs to be defined before running any phpBB
+// script. This might be useful in cases when phpBB is integrated into a
+// larger program.
+if (getenv('PHPBB_NO_COMPOSER_AUTOLOAD'))
+{
+ if (getenv('PHPBB_AUTOLOAD'))
+ {
+ require(getenv('PHPBB_AUTOLOAD'));
+ }
+}
+else
+{
+ if (!file_exists($phpbb_root_path . 'vendor/.composer/autoload.php'))
+ {
+ trigger_error('You have not set up composer dependencies. See http://getcomposer.org/.', E_USER_ERROR);
+ }
+ require($phpbb_root_path . 'vendor/.composer/autoload.php');
+}
+
$starttime = explode(' ', microtime());
$starttime = $starttime[1] + $starttime[0];
diff --git a/phpBB/includes/style/extension_path_provider.php b/phpBB/includes/style/extension_path_provider.php
new file mode 100644
index 0000000000..1fb6580ce1
--- /dev/null
+++ b/phpBB/includes/style/extension_path_provider.php
@@ -0,0 +1,125 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Provides a style resource locator with core style paths and extension style paths
+*
+* Finds installed style paths and makes them available to the resource locator.
+*
+* @package phpBB3
+*/
+class phpbb_style_extension_path_provider extends phpbb_extension_provider implements phpbb_style_path_provider_interface
+{
+ /**
+ * Optional prefix for style paths searched within extensions.
+ *
+ * Empty by default. Relative to the extension directory. As an example, it
+ * could be adm/ for admin style.
+ *
+ * @var string
+ */
+ protected $ext_dir_prefix = '';
+
+ /**
+ * A provider of paths to be searched for styles
+ * @var phpbb_style_path_provider
+ */
+ protected $base_path_provider;
+
+ /**
+ * Constructor stores extension manager
+ *
+ * @param phpbb_extension_manager $extension_manager phpBB extension manager
+ * @param phpbb_style_path_provider $base_path_provider A simple path provider
+ * to provide paths to be located in extensions
+ */
+ public function __construct(phpbb_extension_manager $extension_manager, phpbb_style_path_provider $base_path_provider)
+ {
+ parent::__construct($extension_manager);
+ $this->base_path_provider = $base_path_provider;
+ }
+
+ /**
+ * Sets a prefix for style paths searched within extensions.
+ *
+ * The prefix is inserted between the extension's path e.g. ext/foo/ and
+ * the looked up style path, e.g. styles/bar/. So it should not have a
+ * leading slash, but should have a trailing slash.
+ *
+ * @param string $ext_dir_prefix The prefix including trailing slash
+ * @return null
+ */
+ public function set_ext_dir_prefix($ext_dir_prefix)
+ {
+ $this->ext_dir_prefix = $ext_dir_prefix;
+ }
+
+ /**
+ * Finds style paths using the extension manager
+ *
+ * Locates a path (e.g. styles/prosilver/) in all active extensions.
+ * Then appends the core style paths based in the current working
+ * directory.
+ *
+ * @return array List of style paths
+ */
+ public function find()
+ {
+ $directories = array();
+
+ $finder = $this->extension_manager->get_finder();
+ foreach ($this->base_path_provider as $path)
+ {
+ if ($path && !phpbb_is_absolute($path))
+ {
+ $directories = array_merge($directories, $finder
+ ->directory('/' . $this->ext_dir_prefix . $path)
+ ->get_directories()
+ );
+ }
+ }
+
+ foreach ($this->base_path_provider as $path)
+ {
+ $directories[] = $path;
+ }
+
+ return $directories;
+ }
+
+ /**
+ * Overwrites the current style paths
+ *
+ * @param array $styles An array of style paths. The first element is the main style.
+ * @return null
+ */
+ public function set_styles(array $styles)
+ {
+ $this->base_path_provider->set_styles($styles);
+ $this->items = null;
+ }
+
+ /**
+ * Retrieves the path to the main style passed into set_styles()
+ *
+ * @return string Main style path
+ */
+ public function get_main_style_path()
+ {
+ return $this->base_path_provider->get_main_style_path();
+ }
+}
diff --git a/phpBB/includes/style/path_provider.php b/phpBB/includes/style/path_provider.php
new file mode 100644
index 0000000000..c229af92ba
--- /dev/null
+++ b/phpBB/includes/style/path_provider.php
@@ -0,0 +1,74 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Provides a style resource locator with paths
+*
+* Finds installed style paths and makes them available to the resource locator.
+*
+* @package phpBB3
+*/
+class phpbb_style_path_provider implements IteratorAggregate, phpbb_style_path_provider_interface
+{
+ protected $main_style_name = '';
+ protected $paths = array();
+
+ /**
+ * Ignores the extension dir prefix
+ *
+ * @param string $ext_dir_prefix The prefix including trailing slash
+ * @return null
+ */
+ public function set_ext_dir_prefix($ext_dir_prefix)
+ {
+ }
+
+ /**
+ * Overwrites the current style paths
+ *
+ * The first element of the passed styles map, is considered the main
+ * style and can be retrieved through get_main_style_path().
+ *
+ * @param array $styles An array of style paths. The first element is the main style.
+ * @return null
+ */
+ public function set_styles(array $styles)
+ {
+ $this->paths = $styles;
+ $this->main_style_path = $this->paths[0];
+ }
+
+ /**
+ * Retrieves the path to the main style passed into set_styles()
+ *
+ * @return string Main style path
+ */
+ public function get_main_style_path()
+ {
+ return $this->main_style_path;
+ }
+
+ /**
+ * Retrieve an iterator over all style paths
+ *
+ * @return ArrayIterator An iterator for the array of style paths
+ */
+ public function getIterator()
+ {
+ return new ArrayIterator($this->paths);
+ }
+}
diff --git a/phpBB/includes/style/path_provider_interface.php b/phpBB/includes/style/path_provider_interface.php
new file mode 100644
index 0000000000..7ae94e17f4
--- /dev/null
+++ b/phpBB/includes/style/path_provider_interface.php
@@ -0,0 +1,49 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2011 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Provides a style resource locator with paths
+*
+* Finds installed style paths and makes them available to the resource locator.
+*
+* @package phpBB3
+*/
+interface phpbb_style_path_provider_interface extends Traversable
+{
+ /**
+ * Defines a prefix to use for style paths in extensions
+ *
+ * @param string $ext_dir_prefix The prefix including trailing slash
+ * @return null
+ */
+ public function set_ext_dir_prefix($ext_dir_prefix);
+
+ /**
+ * Overwrites the current style paths
+ *
+ * @param array $styles An array of style paths. The first element is the main style.
+ * @return null
+ */
+ public function set_styles(array $styles);
+
+ /**
+ * Retrieves the path to the main style passed into set_styles()
+ *
+ * @return string Main style path
+ */
+ public function get_main_style_path();
+}
diff --git a/phpBB/includes/template/locator.php b/phpBB/includes/style/resource_locator.php
index d4502d7984..af261534c3 100644
--- a/phpBB/includes/template/locator.php
+++ b/phpBB/includes/style/resource_locator.php
@@ -17,29 +17,42 @@ if (!defined('IN_PHPBB'))
/**
-* Template locator. Maintains mapping from template handles to source paths.
+* Style resource locator.
+* Maintains mapping from template handles to source template file paths.
+* Locates style files: resources (such as .js and .css files) and templates.
*
-* Template locator is aware of template inheritance, and can return actual
-* filesystem paths (i.e., the "primary" template or the "parent" template)
+* Style resource locator is aware of styles tree, and can return actual
+* filesystem paths (i.e., the "child" style or the "parent" styles)
* depending on what files exist.
*
+* Root paths stored in locator are paths to style directories. Templates are
+* stored in subdirectory that $template_path points to.
+*
* @package phpBB3
*/
-class phpbb_template_locator
+class phpbb_style_resource_locator
{
/**
- * Paths to directories that templates are stored in.
+ * Paths to style directories.
* @var array
*/
private $roots = array();
/**
- * Index of the main template in the roots array
+ * Index of the main style in the roots array.
* @var int
*/
private $main_root_id = 0;
/**
+ * Location of templates directory within style directories.
+ * Must have trailing slash. Empty if templates are stored in root
+ * style directory, such as admin control panel templates.
+ * @var string
+ */
+ public $template_path = 'template/';
+
+ /**
* Map from root index to handles to source template file paths.
* Normally it only contains paths for handles that are used
* (or are likely to be used) by the page being rendered and not
@@ -57,34 +70,34 @@ class phpbb_template_locator
private $filenames = array();
/**
- * Set main template location (must have been added through set_paths first).
+ * Set main style location (must have been added through set_paths first).
*
- * @param string $template_path Path to template directory
+ * @param string $style_path Path to style directory
* @return null
*/
- public function set_main_template($template)
+ public function set_main_style($style_path)
{
- $this->main_root_id = array_search($template, $this->roots, true);
+ $this->main_root_id = array_search($style_path, $this->roots, true);
}
/**
- * Sets the list of template paths
+ * Sets the list of style paths
*
- * These paths will be searched for template files in the provided order.
+ * These paths will be searched for style files in the provided order.
* Paths may be outside of phpBB, but templates loaded from these paths
* will still be cached.
*
- * @param array $template_paths An array of paths to template directories
+ * @param array $style_paths An array of paths to style directories
* @return null
*/
- public function set_paths($template_paths)
+ public function set_paths($style_paths)
{
$this->roots = array();
$this->files = array();
$this->filenames = array();
$this->main_root_id = 0;
- foreach ($template_paths as $path)
+ foreach ($style_paths as $path)
{
// Make sure $path has no ending slash
if (substr($path, -1) === '/')
@@ -107,14 +120,14 @@ class phpbb_template_locator
{
if (empty($filename))
{
- trigger_error("template locator: set_filenames: Empty filename specified for $handle", E_USER_ERROR);
+ trigger_error("style resource locator: set_filenames: Empty filename specified for $handle", E_USER_ERROR);
}
$this->filename[$handle] = $filename;
foreach ($this->roots as $root_index => $root)
{
- $this->files[$root_index][$handle] = $root . '/' . $filename;
+ $this->files[$root_index][$handle] = $root . '/' . $this->template_path . $filename;
}
}
}
@@ -133,37 +146,37 @@ class phpbb_template_locator
{
if (!isset($this->filename[$handle]))
{
- trigger_error("template locator: get_filename_for_handle: No file specified for handle $handle", E_USER_ERROR);
+ trigger_error("style resource locator: get_filename_for_handle: No file specified for handle $handle", E_USER_ERROR);
}
return $this->filename[$handle];
}
/**
* Determines the source file path for a template handle without
- * regard for template inheritance.
+ * regard for styles tree.
*
- * This function returns the path in "primary" template directory
+ * This function returns the path in "primary" style directory
* corresponding to the given template handle. That path may or
* may not actually exist on the filesystem. Because this function
* does not perform stat calls to determine whether the path it
* returns actually exists, it is faster than get_source_file_for_handle.
*
* Use get_source_file_for_handle to obtain the actual path that is
- * guaranteed to exist (which might come from the parent/fallback
- * template directory if template inheritance is used).
+ * guaranteed to exist (which might come from the parent style
+ * directory if primary style has parent styles).
*
* This function will trigger an error if the handle was never
* associated with a template file via set_filenames.
*
* @param $handle string Template handle
- * @return string Path to source file path in primary template directory
+ * @return string Path to source file path in primary style directory
*/
public function get_virtual_source_file_for_handle($handle)
{
// If we don't have a file assigned to this handle, die.
if (!isset($this->files[$this->main_root_id][$handle]))
{
- trigger_error("template locator: No file specified for handle $handle", E_USER_ERROR);
+ trigger_error("style resource locator: No file specified for handle $handle", E_USER_ERROR);
}
$source_file = $this->files[$this->main_root_id][$handle];
@@ -172,7 +185,7 @@ class phpbb_template_locator
/**
* Determines the source file path for a template handle, accounting
- * for template inheritance and verifying that the path exists.
+ * for styles tree and verifying that the path exists.
*
* This function returns the actual path that may be compiled for
* the specified template handle. It will trigger an error if
@@ -181,7 +194,7 @@ class phpbb_template_locator
* filesystem.
*
* Use get_virtual_source_file_for_handle to just resolve a template
- * handle to a path without any filesystem or inheritance checks.
+ * handle to a path without any filesystem or styles tree checks.
*
* @param string $handle Template handle (i.e. "friendly" template name)
* @return string Source file path
@@ -191,7 +204,7 @@ class phpbb_template_locator
// If we don't have a file assigned to this handle, die.
if (!isset($this->files[$this->main_root_id][$handle]))
{
- trigger_error("template locator: No file specified for handle $handle", E_USER_ERROR);
+ trigger_error("style resource locator: No file specified for handle $handle", E_USER_ERROR);
}
// locate a source file that exists
@@ -206,7 +219,7 @@ class phpbb_template_locator
// search failed
if (!file_exists($source_file))
{
- trigger_error("template locator: File for handle $handle does not exist. Could not find: $tried", E_USER_ERROR);
+ trigger_error("style resource locator: File for handle $handle does not exist. Could not find: $tried", E_USER_ERROR);
}
return $source_file;
diff --git a/phpBB/includes/style/style.php b/phpBB/includes/style/style.php
new file mode 100644
index 0000000000..539a2642ee
--- /dev/null
+++ b/phpBB/includes/style/style.php
@@ -0,0 +1,151 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2005 phpBB Group, sections (c) 2001 ispi of Lincoln Inc
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Base Style class.
+* @package phpBB3
+*/
+class phpbb_style
+{
+ /**
+ * @var phpbb_style_template Template class.
+ * Handles everything related to templates.
+ */
+ private $template;
+
+ /**
+ * @var string phpBB root path
+ */
+ private $phpbb_root_path;
+
+ /**
+ * @var phpEx PHP file extension
+ */
+ private $phpEx;
+
+ /**
+ * @var phpbb_config phpBB config instance
+ */
+ private $config;
+
+ /**
+ * @var user current user
+ */
+ private $user;
+
+ /**
+ * Style resource locator
+ * @var phpbb_style_resource_locator
+ */
+ private $locator;
+
+ /**
+ * Style path provider
+ * @var phpbb_style_path_provider
+ */
+ private $provider;
+
+ /**
+ * Constructor.
+ *
+ * @param string $phpbb_root_path phpBB root path
+ * @param user $user current user
+ * @param phpbb_style_resource_locator $locator style resource locator
+ * @param phpbb_style_path_provider $provider style path provider
+ * @param phpbb_style_template $template template
+ */
+ public function __construct($phpbb_root_path, $phpEx, $config, $user, phpbb_style_resource_locator $locator, phpbb_style_path_provider_interface $provider, phpbb_style_template $template)
+ {
+ $this->phpbb_root_path = $phpbb_root_path;
+ $this->phpEx = $phpEx;
+ $this->config = $config;
+ $this->user = $user;
+ $this->locator = $locator;
+ $this->provider = $provider;
+ $this->template = $template;
+ }
+
+ /**
+ * Set style location based on (current) user's chosen style.
+ */
+ public function set_style()
+ {
+ $style_name = $this->user->theme['style_path'];
+ $style_dirs = ($this->user->theme['style_parent_id']) ? array_reverse(explode('/', $this->user->theme['style_parent_tree'])) : array();
+ $paths = array($this->get_style_path($style_name));
+ foreach ($style_dirs as $dir)
+ {
+ $paths[] = $this->get_style_path($dir);
+ }
+
+ return $this->set_custom_style($style_name, $paths);
+ }
+
+ /**
+ * Set custom style location (able to use directory outside of phpBB).
+ *
+ * Note: Templates are still compiled to phpBB's cache directory.
+ *
+ * @param string $name Name of style, used for cache prefix. Examples: "admin", "prosilver"
+ * @param array or string $paths Array of style paths, relative to current root directory
+ * @param string $template_path Path to templates, relative to style directory. False if path should not be changed.
+ */
+ public function set_custom_style($name, $paths, $template_path = false)
+ {
+ if (is_string($paths))
+ {
+ $paths = array($paths);
+ }
+
+ $this->provider->set_styles($paths);
+ $this->locator->set_paths($this->provider);
+ $this->locator->set_main_style($this->provider->get_main_style_path());
+
+ $this->template->cachepath = $this->phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $name) . '_';
+
+ $this->template->context = new phpbb_style_template_context();
+
+ if ($template_path !== false)
+ {
+ $this->template->template_path = $this->locator->template_path = $template_path;
+ }
+
+ return true;
+ }
+
+ /**
+ * Get location of style directory for specific style_path
+ *
+ * @param string $path Style path, such as "prosilver"
+ * @return string Path to style directory, relative to current path
+ */
+ public function get_style_path($path)
+ {
+ return $this->phpbb_root_path . 'styles/' . $path;
+ }
+
+ /**
+ * Defines a prefix to use for style paths in extensions
+ *
+ * @param string $ext_dir_prefix The prefix including trailing slash
+ * @return null
+ */
+ public function set_ext_dir_prefix($ext_dir_prefix)
+ {
+ $this->provider->set_ext_dir_prefix($ext_dir_prefix);
+ }
+}
diff --git a/phpBB/includes/template/template.php b/phpBB/includes/style/template.php
index 989322320b..21a2e821dd 100644
--- a/phpBB/includes/template/template.php
+++ b/phpBB/includes/style/template.php
@@ -29,13 +29,13 @@ if (!defined('IN_PHPBB'))
* Base Template class.
* @package phpBB3
*/
-class phpbb_template
+class phpbb_style_template
{
/**
- * @var phpbb_template_context Template context.
+ * @var phpbb_style_template_context Template context.
* Stores template data used during template rendering.
*/
- private $context;
+ public $context;
/**
* @var string Path of the cache directory for the template
@@ -63,88 +63,43 @@ class phpbb_template
private $user;
/**
- * Template locator
- * @var phpbb_template_locator
+ * Style resource locator
+ * @var phpbb_style_resource_locator
*/
private $locator;
/**
* Template path provider
- * @var phpbb_template_path_provider
+ * @var phpbb_style_path_provider
*/
private $provider;
/**
+ * Location of templates directory within style directories
+ * @var string
+ */
+ public $template_path = 'template/';
+
+ /**
* Constructor.
*
* @param string $phpbb_root_path phpBB root path
* @param user $user current user
- * @param phpbb_template_locator $locator template locator
- * @param phpbb_template_path_provider $provider template path provider
+ * @param phpbb_style_resource_locator $locator style resource locator
+ * @param phpbb_style_path_provider $provider style path provider
*/
- public function __construct($phpbb_root_path, $phpEx, $config, $user, phpbb_template_locator $locator, phpbb_template_path_provider_interface $provider)
+ public function __construct($phpbb_root_path, $phpEx, $config, $user, phpbb_style_resource_locator $locator, phpbb_style_path_provider_interface $provider)
{
$this->phpbb_root_path = $phpbb_root_path;
$this->phpEx = $phpEx;
$this->config = $config;
$this->user = $user;
$this->locator = $locator;
+ $this->template_path = $this->locator->template_path;
$this->provider = $provider;
}
/**
- * Set template location based on (current) user's chosen style.
- */
- public function set_template()
- {
- $template_name = $this->user->theme['template_path'];
- $fallback_name = ($this->user->theme['template_inherits_id']) ? $this->user->theme['template_inherit_path'] : false;
-
- return $this->set_custom_template(false, $template_name, false, $fallback_name);
- }
-
- /**
- * Defines a prefix to use for template paths in extensions
- *
- * @param string $ext_dir_prefix The prefix including trailing slash
- * @return null
- */
- public function set_ext_dir_prefix($ext_dir_prefix)
- {
- $this->provider->set_ext_dir_prefix($ext_dir_prefix);
- }
-
- /**
- * Set custom template location (able to use directory outside of phpBB).
- *
- * Note: Templates are still compiled to phpBB's cache directory.
- *
- * @param string $template_path Path to template directory
- * @param string $template_name Name of template
- * @param string $fallback_template_path Path to fallback template
- * @param string $fallback_template_name Name of fallback template
- */
- public function set_custom_template($template_path, $template_name, $fallback_template_path = false, $fallback_template_name = false)
- {
- $templates = array($template_name => $template_path);
-
- if ($fallback_template_path !== false)
- {
- $templates[$fallback_template_name] = $fallback_template_path;
- }
-
- $this->provider->set_templates($templates, $this->phpbb_root_path);
- $this->locator->set_paths($this->provider);
- $this->locator->set_main_template($this->provider->get_main_template_path());
-
- $this->cachepath = $this->phpbb_root_path . 'cache/tpl_' . str_replace('_', '-', $template_name) . '_';
-
- $this->context = new phpbb_template_context();
-
- return true;
- }
-
- /**
* Sets the template filenames for handles.
*
* @param array $filname_array Should be a hash of handle => filename pairs.
@@ -298,15 +253,15 @@ class phpbb_template
* configuration setting may be used to force templates to be always
* recompiled.
*
- * Returns an object implementing phpbb_template_renderer, or null
+ * Returns an object implementing phpbb_style_template_renderer, or null
* if template loading or compilation failed. Call render() on the
* renderer to display the template. This will result in template
* contents sent to the output stream (unless, of course, output
* buffering is in effect).
*
* @param string $handle Handle of the template to load
- * @return phpbb_template_renderer Template renderer object, or null on failure
- * @uses template_compile is used to compile template source
+ * @return phpbb_style_template_renderer Template renderer object, or null on failure
+ * @uses phpbb_style_template_compile is used to compile template source
*/
private function _tpl_load($handle)
{
@@ -330,18 +285,18 @@ class phpbb_template
// Recompile page if the original template is newer, otherwise load the compiled version
if (!$recompile)
{
- return new phpbb_template_renderer_include($output_file, $this);
+ return new phpbb_style_template_renderer_include($output_file, $this);
}
- $compile = new phpbb_template_compile($this->config['tpl_allow_php']);
+ $compile = new phpbb_style_template_compile($this->config['tpl_allow_php']);
if ($compile->compile_file_to_file($source_file, $output_file) !== false)
{
- $renderer = new phpbb_template_renderer_include($output_file, $this);
+ $renderer = new phpbb_style_template_renderer_include($output_file, $this);
}
else if (($code = $compile->compile_file($source_file)) !== false)
{
- $renderer = new phpbb_template_renderer_eval($code, $this);
+ $renderer = new phpbb_style_template_renderer_eval($code, $this);
}
else
{
@@ -378,7 +333,9 @@ class phpbb_template
}
/**
- * Assign a single variable to a single key
+ * Assign a single scalar value to a single key.
+ *
+ * Value can be a string, an integer or a boolean.
*
* @param string $varname Variable name
* @param string $varval Value to assign to variable
@@ -388,7 +345,20 @@ class phpbb_template
$this->context->assign_var($varname, $varval);
}
- // Docstring is copied from phpbb_template_context method with the same name.
+ /**
+ * Append text to the string value stored in a key.
+ *
+ * Text is appended using the string concatenation operator (.).
+ *
+ * @param string $varname Variable name
+ * @param string $varval Value to append to variable
+ */
+ public function append_var($varname, $varval)
+ {
+ $this->context->append_var($varname, $varval);
+ }
+
+ // Docstring is copied from phpbb_style_template_context method with the same name.
/**
* Assign key variable pairs from an array to a specified block
* @param string $blockname Name of block to assign $vararray to
@@ -399,7 +369,7 @@ class phpbb_template
return $this->context->assign_block_vars($blockname, $vararray);
}
- // Docstring is copied from phpbb_template_context method with the same name.
+ // Docstring is copied from phpbb_style_template_context method with the same name.
/**
* Change already assigned key variable pair (one-dimensional - single loop entry)
*
diff --git a/phpBB/includes/template/compile.php b/phpBB/includes/style/template_compile.php
index b0009421c5..3ef3fffc00 100644
--- a/phpBB/includes/template/compile.php
+++ b/phpBB/includes/style/template_compile.php
@@ -15,7 +15,7 @@ if (!defined('IN_PHPBB'))
exit;
}
-stream_filter_register('phpbb_template', 'phpbb_template_filter');
+stream_filter_register('phpbb_template', 'phpbb_style_template_filter');
/**
* Extension of template class - Functions needed for compiling templates only.
@@ -23,7 +23,7 @@ stream_filter_register('phpbb_template', 'phpbb_template_filter');
* @package phpBB3
* @uses template_filter As a PHP stream filter to perform compilation of templates
*/
-class phpbb_template_compile
+class phpbb_style_template_compile
{
/**
* Whether <!-- PHP --> tags are allowed
diff --git a/phpBB/includes/template/context.php b/phpBB/includes/style/template_context.php
index 65a3531bc5..b22f77da2e 100644
--- a/phpBB/includes/template/context.php
+++ b/phpBB/includes/style/template_context.php
@@ -20,7 +20,7 @@ if (!defined('IN_PHPBB'))
*
* @package phpBB3
*/
-class phpbb_template_context
+class phpbb_style_template_context
{
/**
* variable that holds all the data we'll be substituting into
@@ -53,7 +53,9 @@ class phpbb_template_context
}
/**
- * Assign a single variable to a single key
+ * Assign a single scalar value to a single key.
+ *
+ * Value can be a string, an integer or a boolean.
*
* @param string $varname Variable name
* @param string $varval Value to assign to variable
@@ -66,10 +68,25 @@ class phpbb_template_context
}
/**
+ * Append text to the string value stored in a key.
+ *
+ * Text is appended using the string concatenation operator (.).
+ *
+ * @param string $varname Variable name
+ * @param string $varval Value to append to variable
+ */
+ public function append_var($varname, $varval)
+ {
+ $this->rootref[$varname] = (isset($this->rootref[$varname]) ? $this->rootref[$varname] : '') . $varval;
+
+ return true;
+ }
+
+ /**
* Returns a reference to template data array.
*
* This function is public so that template renderer may invoke it.
- * Users should alter template variables via functions in phpbb_template.
+ * Users should alter template variables via functions in phpbb_style_template.
*
* Note: modifying returned array will affect data stored in the context.
*
diff --git a/phpBB/includes/template/filter.php b/phpBB/includes/style/template_filter.php
index f55c8d7e9c..04fe85e07f 100644
--- a/phpBB/includes/template/filter.php
+++ b/phpBB/includes/style/template_filter.php
@@ -35,7 +35,7 @@ if (!defined('IN_PHPBB'))
* @see template_compile
* @package phpBB3
*/
-class phpbb_template_filter extends php_user_filter
+class phpbb_style_template_filter extends php_user_filter
{
const REGEX_NS = '[a-z_][a-z_0-9]+';
diff --git a/phpBB/includes/template/renderer.php b/phpBB/includes/style/template_renderer.php
index 30e234a733..bd2a786e86 100644
--- a/phpBB/includes/template/renderer.php
+++ b/phpBB/includes/style/template_renderer.php
@@ -23,12 +23,12 @@ if (!defined('IN_PHPBB'))
*
* @package phpBB3
*/
-interface phpbb_template_renderer
+interface phpbb_style_template_renderer
{
/**
* Displays the template managed by this renderer.
*
- * @param phpbb_template_context $context Template context to use
+ * @param phpbb_style_template_context $context Template context to use
* @param array $lang Language entries to use
*/
public function render($context, $lang);
diff --git a/phpBB/includes/template/renderer_eval.php b/phpBB/includes/style/template_renderer_eval.php
index f8e4cb7b10..3e08b06e69 100644
--- a/phpBB/includes/template/renderer_eval.php
+++ b/phpBB/includes/style/template_renderer_eval.php
@@ -21,7 +21,7 @@ if (!defined('IN_PHPBB'))
*
* @package phpBB3
*/
-class phpbb_template_renderer_eval implements phpbb_template_renderer
+class phpbb_style_template_renderer_eval implements phpbb_style_template_renderer
{
/**
* Template code to be eval'ed.
@@ -33,7 +33,7 @@ class phpbb_template_renderer_eval implements phpbb_template_renderer
* Template includes are delegated to template object $template.
*
* @param string $code php code of the template
- * @param phpbb_template $template template object
+ * @param phpbb_style_template $template template object
*/
public function __construct($code, $template)
{
@@ -45,7 +45,7 @@ class phpbb_template_renderer_eval implements phpbb_template_renderer
* Displays the template managed by this renderer by eval'ing php code
* of the template.
*
- * @param phpbb_template_context $context Template context to use
+ * @param phpbb_style_template_context $context Template context to use
* @param array $lang Language entries to use
*/
public function render($context, $lang)
diff --git a/phpBB/includes/template/renderer_include.php b/phpBB/includes/style/template_renderer_include.php
index f5c9026abf..91c1a1bb65 100644
--- a/phpBB/includes/template/renderer_include.php
+++ b/phpBB/includes/style/template_renderer_include.php
@@ -22,7 +22,7 @@ if (!defined('IN_PHPBB'))
*
* @package phpBB3
*/
-class phpbb_template_renderer_include implements phpbb_template_renderer
+class phpbb_style_template_renderer_include implements phpbb_style_template_renderer
{
/**
* Template path to be included.
@@ -45,7 +45,7 @@ class phpbb_template_renderer_include implements phpbb_template_renderer
* Displays the template managed by this renderer by including
* the php file containing the template.
*
- * @param phpbb_template_context $context Template context to use
+ * @param phpbb_style_template_context $context Template context to use
* @param array $lang Language entries to use
*/
public function render($context, $lang)
diff --git a/phpBB/includes/template/extension_path_provider.php b/phpBB/includes/template/extension_path_provider.php
deleted file mode 100644
index 2897f60ac1..0000000000
--- a/phpBB/includes/template/extension_path_provider.php
+++ /dev/null
@@ -1,130 +0,0 @@
-<?php
-/**
-*
-* @package phpBB3
-* @copyright (c) 2011 phpBB Group
-* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Provides a template locator with core template paths and extension template paths
-*
-* Finds installed template paths and makes them available to the locator.
-*
-* @package phpBB3
-*/
-class phpbb_template_extension_path_provider extends phpbb_extension_provider implements phpbb_template_path_provider_interface
-{
- /**
- * Optional prefix for template paths searched within extensions.
- *
- * Empty by default. Relative to the extension directory. As an example, it
- * could be adm/ for admin templates.
- *
- * @var string
- */
- protected $ext_dir_prefix = '';
-
- /**
- * A provider of paths to be searched for templates
- * @var phpbb_template_path_provider
- */
- protected $base_path_provider;
-
- /**
- * Constructor stores extension manager
- *
- * @param phpbb_extension_manager $extension_manager phpBB extension manager
- * @param phpbb_template_path_provider $base_path_provider A simple path provider
- * to provide paths to be located in extensions
- */
- public function __construct(phpbb_extension_manager $extension_manager, phpbb_template_path_provider $base_path_provider)
- {
- parent::__construct($extension_manager);
- $this->base_path_provider = $base_path_provider;
- }
-
- /**
- * Sets a prefix for template paths searched within extensions.
- *
- * The prefix is inserted between the extension's path e.g. ext/foo/ and
- * the looked up template path, e.g. styles/bar/template/some.html. So it
- * should not have a leading slash, but should have a trailing slash.
- *
- * @param string $ext_dir_prefix The prefix including trailing slash
- * @return null
- */
- public function set_ext_dir_prefix($ext_dir_prefix)
- {
- $this->ext_dir_prefix = $ext_dir_prefix;
- }
-
- /**
- * Finds template paths using the extension manager
- *
- * Locates a path (e.g. styles/prosilver/template/) in all active extensions.
- * Then appends the core template paths based in the current working
- * directory.
- *
- * @return array List of template paths
- */
- public function find()
- {
- $directories = array();
-
- $finder = $this->extension_manager->get_finder();
- foreach ($this->base_path_provider as $path)
- {
- if ($path && !phpbb_is_absolute($path))
- {
- $directories = array_merge($directories, $finder
- ->directory('/' . $this->ext_dir_prefix . $path)
- ->get_directories()
- );
- }
- }
-
- foreach ($this->base_path_provider as $path)
- {
- $directories[] = $path;
- }
-
- return $directories;
- }
-
- /**
- * Overwrites the current template names and paths
- *
- * @param array $templates An associative map from template names to paths.
- * The first element is the main template.
- * If the path is false, it will be generated from
- * the supplied name.
- * @param string $style_root_path The root directory for styles identified
- * by name only.
- * @return null
- */
- public function set_templates(array $templates, $style_root_path)
- {
- $this->base_path_provider->set_templates($templates, $style_root_path);
- $this->items = null;
- }
-
- /**
- * Retrieves the path to the main template passed into set_templates()
- *
- * @return string Main template path
- */
- public function get_main_template_path()
- {
- return $this->base_path_provider->get_main_template_path();
- }
-}
diff --git a/phpBB/includes/template/path_provider.php b/phpBB/includes/template/path_provider.php
deleted file mode 100644
index b0b545973d..0000000000
--- a/phpBB/includes/template/path_provider.php
+++ /dev/null
@@ -1,102 +0,0 @@
-<?php
-/**
-*
-* @package phpBB3
-* @copyright (c) 2011 phpBB Group
-* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Provides a template locator with paths
-*
-* Finds installed template paths and makes them available to the locator.
-*
-* @package phpBB3
-*/
-class phpbb_template_path_provider implements IteratorAggregate, phpbb_template_path_provider_interface
-{
- protected $main_template_name = '';
- protected $paths = array();
-
- /**
- * Ignores the extension dir prefix
- *
- * @param string $ext_dir_prefix The prefix including trailing slash
- * @return null
- */
- public function set_ext_dir_prefix($ext_dir_prefix)
- {
- }
-
- /**
- * Overwrites the current template names and paths
- *
- * The first element of the passed templates map, is considered the main
- * template and can be retrieved through get_main_template_path().
- *
- * @param array $templates An associative map from template names to paths.
- * The first element is the main template.
- * If the path is false, it will be generated from
- * the supplied name.
- * @param string $style_root_path The root directory for styles identified
- * by name only.
- * @return null
- */
- public function set_templates(array $templates, $style_root_path)
- {
- $this->paths = array();
-
- foreach ($templates as $name => $path)
- {
- if (!$path)
- {
- $path = $style_root_path . $this->template_root_for_style($name);
- }
-
- $this->paths[] = $path;
- }
-
- $this->main_template_path = $this->paths[0];
- }
-
- /**
- * Retrieves the path to the main template passed into set_templates()
- *
- * @return string Main template path
- */
- public function get_main_template_path()
- {
- return $this->main_template_path;
- }
-
- /**
- * Converts a style name to relative (to board root or extension) path to
- * the style's template files.
- *
- * @param $style_name string Style name
- * @return string Path to style template files
- */
- private function template_root_for_style($style_name)
- {
- return 'styles/' . $style_name . '/template';
- }
-
- /**
- * Retrieve an iterator over all template paths
- *
- * @return ArrayIterator An iterator for the array of template paths
- */
- public function getIterator()
- {
- return new ArrayIterator($this->paths);
- }
-}
diff --git a/phpBB/includes/template/path_provider_interface.php b/phpBB/includes/template/path_provider_interface.php
deleted file mode 100644
index 8b3a406d2a..0000000000
--- a/phpBB/includes/template/path_provider_interface.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-/**
-*
-* @package phpBB3
-* @copyright (c) 2011 phpBB Group
-* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Provides a template locator with paths
-*
-* Finds installed template paths and makes them available to the locator.
-*
-* @package phpBB3
-*/
-interface phpbb_template_path_provider_interface extends Traversable
-{
- /**
- * Defines a prefix to use for template paths in extensions
- *
- * @param string $ext_dir_prefix The prefix including trailing slash
- * @return null
- */
- public function set_ext_dir_prefix($ext_dir_prefix);
-
- /**
- * Overwrites the current template names and paths
- *
- * @param array $templates An associative map from template names to paths.
- * The first element is the main template.
- * If the path is false, it will be generated from
- * the supplied name.
- * @param string $style_root_path The root directory for styles identified
- * by name only.
- * @return null
- */
- public function set_templates(array $templates, $style_root_path);
-
- /**
- * Retrieves the path to the main template passed into set_templates()
- *
- * @return string Main template path
- */
- public function get_main_template_path();
-}
diff --git a/phpBB/includes/ucp/ucp_remind.php b/phpBB/includes/ucp/ucp_remind.php
index bcd4e261fe..4f65ed1866 100644
--- a/phpBB/includes/ucp/ucp_remind.php
+++ b/phpBB/includes/ucp/ucp_remind.php
@@ -66,7 +66,7 @@ class ucp_remind
}
// Check users permissions
- $auth2 = new auth();
+ $auth2 = new phpbb_auth();
$auth2->acl($user_row);
if (!$auth2->acl_get('u_chgpasswd'))
diff --git a/phpBB/includes/ucp/ucp_zebra.php b/phpBB/includes/ucp/ucp_zebra.php
index 004f3b80aa..efe928b387 100644
--- a/phpBB/includes/ucp/ucp_zebra.php
+++ b/phpBB/includes/ucp/ucp_zebra.php
@@ -25,7 +25,7 @@ class ucp_zebra
function main($id, $mode)
{
- global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx;
+ global $config, $db, $user, $auth, $template, $phpbb_root_path, $phpEx, $request;
$submit = (isset($_POST['submit']) || isset($_GET['add']) || isset($_GET['remove'])) ? true : false;
$s_hidden_fields = '';
@@ -198,8 +198,24 @@ class ucp_zebra
}
}
}
-
- if ($updated)
+
+ if ($request->is_ajax())
+ {
+ $message = ($updated) ? $user->lang[$l_mode . '_UPDATED'] : implode('<br />', $error);
+
+ $json_response = new phpbb_json_response;
+ $json_response->send(array(
+ 'success' => $updated,
+
+ 'MESSAGE_TITLE' => $user->lang['INFORMATION'],
+ 'MESSAGE_TEXT' => $message,
+ 'REFRESH_DATA' => array(
+ 'time' => 3,
+ 'url' => $this->u_action
+ )
+ ));
+ }
+ else if ($updated)
{
meta_refresh(3, $this->u_action);
$message = $user->lang[$l_mode . '_UPDATED'] . '<br />' . implode('<br />', $error) . ((sizeof($error)) ? '<br />' : '') . '<br />' . sprintf($user->lang['RETURN_UCP'], '<a href="' . $this->u_action . '">', '</a>');
diff --git a/phpBB/includes/user.php b/phpBB/includes/user.php
new file mode 100644
index 0000000000..1676f82ccb
--- /dev/null
+++ b/phpBB/includes/user.php
@@ -0,0 +1,851 @@
+<?php
+/**
+*
+* @package phpBB3
+* @copyright (c) 2005 phpBB Group
+* @license http://opensource.org/licenses/gpl-2.0.php GNU General Public License v2
+*
+*/
+
+/**
+* @ignore
+*/
+if (!defined('IN_PHPBB'))
+{
+ exit;
+}
+
+/**
+* Base user class
+*
+* This is the overarching class which contains (through session extend)
+* all methods utilised for user functionality during a session.
+*
+* @package phpBB3
+*/
+class phpbb_user extends phpbb_session
+{
+ var $lang = array();
+ var $help = array();
+ var $theme = array();
+ var $date_format;
+ var $timezone;
+ var $dst;
+
+ var $lang_name = false;
+ var $lang_id = false;
+ var $lang_path;
+ var $img_lang;
+ var $img_array = array();
+
+ // Able to add new options (up to id 31)
+ var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'popuppm' => 10, 'sig_bbcode' => 15, 'sig_smilies' => 16, 'sig_links' => 17);
+
+ /**
+ * Constructor to set the lang path
+ */
+ function __construct()
+ {
+ global $phpbb_root_path;
+
+ $this->lang_path = $phpbb_root_path . 'language/';
+ }
+
+ /**
+ * Function to set custom language path (able to use directory outside of phpBB)
+ *
+ * @param string $lang_path New language path used.
+ * @access public
+ */
+ function set_custom_lang_path($lang_path)
+ {
+ $this->lang_path = $lang_path;
+
+ if (substr($this->lang_path, -1) != '/')
+ {
+ $this->lang_path .= '/';
+ }
+ }
+
+ /**
+ * Setup basic user-specific items (style, language, ...)
+ */
+ function setup($lang_set = false, $style_id = false)
+ {
+ global $db, $style, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache;
+
+ if ($this->data['user_id'] != ANONYMOUS)
+ {
+ $this->lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']);
+
+ $this->date_format = $this->data['user_dateformat'];
+ $this->timezone = $this->data['user_timezone'] * 3600;
+ $this->dst = $this->data['user_dst'] * 3600;
+ }
+ else
+ {
+ $this->lang_name = basename($config['default_lang']);
+ $this->date_format = $config['default_dateformat'];
+ $this->timezone = $config['board_timezone'] * 3600;
+ $this->dst = $config['board_dst'] * 3600;
+
+ /**
+ * If a guest user is surfing, we try to guess his/her language first by obtaining the browser language
+ * If re-enabled we need to make sure only those languages installed are checked
+ * Commented out so we do not loose the code.
+
+ if ($request->header('Accept-Language'))
+ {
+ $accept_lang_ary = explode(',', $request->header('Accept-Language'));
+
+ foreach ($accept_lang_ary as $accept_lang)
+ {
+ // Set correct format ... guess full xx_YY form
+ $accept_lang = substr($accept_lang, 0, 2) . '_' . strtoupper(substr($accept_lang, 3, 2));
+ $accept_lang = basename($accept_lang);
+
+ if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx"))
+ {
+ $this->lang_name = $config['default_lang'] = $accept_lang;
+ break;
+ }
+ else
+ {
+ // No match on xx_YY so try xx
+ $accept_lang = substr($accept_lang, 0, 2);
+ $accept_lang = basename($accept_lang);
+
+ if (file_exists($this->lang_path . $accept_lang . "/common.$phpEx"))
+ {
+ $this->lang_name = $config['default_lang'] = $accept_lang;
+ break;
+ }
+ }
+ }
+ }
+ */
+ }
+
+ // We include common language file here to not load it every time a custom language file is included
+ $lang = &$this->lang;
+
+ // Do not suppress error if in DEBUG_EXTRA mode
+ $include_result = (defined('DEBUG_EXTRA')) ? (include $this->lang_path . $this->lang_name . "/common.$phpEx") : (@include $this->lang_path . $this->lang_name . "/common.$phpEx");
+
+ if ($include_result === false)
+ {
+ die('Language file ' . $this->lang_path . $this->lang_name . "/common.$phpEx" . " couldn't be opened.");
+ }
+
+ $this->add_lang($lang_set);
+ unset($lang_set);
+
+ $style_request = request_var('style', 0);
+ if ($style_request && $auth->acl_get('a_styles') && !defined('ADMIN_START'))
+ {
+ global $SID, $_EXTRA_URL;
+
+ $style_id = $style_request;
+ $SID .= '&amp;style=' . $style_id;
+ $_EXTRA_URL = array('style=' . $style_id);
+ }
+ else
+ {
+ // Set up style
+ $style_id = ($style_id) ? $style_id : ((!$config['override_user_style']) ? $this->data['user_style'] : $config['default_style']);
+ }
+
+ $sql = 'SELECT *
+ FROM ' . STYLES_TABLE . " s
+ WHERE s.style_id = $style_id";
+ $result = $db->sql_query($sql, 3600);
+ $this->theme = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+
+ // User has wrong style
+ if (!$this->theme && $style_id == $this->data['user_style'])
+ {
+ $style_id = $this->data['user_style'] = $config['default_style'];
+
+ $sql = 'UPDATE ' . USERS_TABLE . "
+ SET user_style = $style_id
+ WHERE user_id = {$this->data['user_id']}";
+ $db->sql_query($sql);
+
+ $sql = 'SELECT *
+ FROM ' . STYLES_TABLE . " s
+ WHERE s.style_id = $style_id";
+ $result = $db->sql_query($sql, 3600);
+ $this->theme = $db->sql_fetchrow($result);
+ $db->sql_freeresult($result);
+ }
+
+ if (!$this->theme)
+ {
+ trigger_error('Could not get style data', E_USER_ERROR);
+ }
+
+ // Now parse the cfg file and cache it
+ $parsed_items = $cache->obtain_cfg_items($this->theme);
+
+ // We are only interested in the theme configuration for now
+ $parsed_items = $parsed_items['theme'];
+
+ $check_for = array(
+ 'pagination_sep' => (string) ', '
+ );
+
+ foreach ($check_for as $key => $default_value)
+ {
+ $this->theme[$key] = (isset($parsed_items[$key])) ? $parsed_items[$key] : $default_value;
+ settype($this->theme[$key], gettype($default_value));
+
+ if (is_string($default_value))
+ {
+ $this->theme[$key] = htmlspecialchars($this->theme[$key]);
+ }
+ }
+
+ $style->set_style();
+
+ $this->img_lang = $this->lang_name;
+
+ // Call phpbb_user_session_handler() in case external application want to "bend" some variables or replace classes...
+ // After calling it we continue script execution...
+ phpbb_user_session_handler();
+
+ // If this function got called from the error handler we are finished here.
+ if (defined('IN_ERROR_HANDLER'))
+ {
+ return;
+ }
+
+ // Disable board if the install/ directory is still present
+ // For the brave development army we do not care about this, else we need to comment out this everytime we develop locally
+ if (!defined('DEBUG_EXTRA') && !defined('ADMIN_START') && !defined('IN_INSTALL') && !defined('IN_LOGIN') && file_exists($phpbb_root_path . 'install') && !is_file($phpbb_root_path . 'install'))
+ {
+ // Adjust the message slightly according to the permissions
+ if ($auth->acl_gets('a_', 'm_') || $auth->acl_getf_global('m_'))
+ {
+ $message = 'REMOVE_INSTALL';
+ }
+ else
+ {
+ $message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE';
+ }
+ trigger_error($message);
+ }
+
+ // Is board disabled and user not an admin or moderator?
+ if ($config['board_disable'] && !defined('IN_LOGIN') && !$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_'))
+ {
+ if ($this->data['is_bot'])
+ {
+ send_status_line(503, 'Service Unavailable');
+ }
+
+ $message = (!empty($config['board_disable_msg'])) ? $config['board_disable_msg'] : 'BOARD_DISABLE';
+ trigger_error($message);
+ }
+
+ // Is load exceeded?
+ if ($config['limit_load'] && $this->load !== false)
+ {
+ if ($this->load > floatval($config['limit_load']) && !defined('IN_LOGIN') && !defined('IN_ADMIN'))
+ {
+ // Set board disabled to true to let the admins/mods get the proper notification
+ $config['board_disable'] = '1';
+
+ if (!$auth->acl_gets('a_', 'm_') && !$auth->acl_getf_global('m_'))
+ {
+ if ($this->data['is_bot'])
+ {
+ send_status_line(503, 'Service Unavailable');
+ }
+ trigger_error('BOARD_UNAVAILABLE');
+ }
+ }
+ }
+
+ if (isset($this->data['session_viewonline']))
+ {
+ // Make sure the user is able to hide his session
+ if (!$this->data['session_viewonline'])
+ {
+ // Reset online status if not allowed to hide the session...
+ if (!$auth->acl_get('u_hideonline'))
+ {
+ $sql = 'UPDATE ' . SESSIONS_TABLE . '
+ SET session_viewonline = 1
+ WHERE session_user_id = ' . $this->data['user_id'];
+ $db->sql_query($sql);
+ $this->data['session_viewonline'] = 1;
+ }
+ }
+ else if (!$this->data['user_allow_viewonline'])
+ {
+ // the user wants to hide and is allowed to -> cloaking device on.
+ if ($auth->acl_get('u_hideonline'))
+ {
+ $sql = 'UPDATE ' . SESSIONS_TABLE . '
+ SET session_viewonline = 0
+ WHERE session_user_id = ' . $this->data['user_id'];
+ $db->sql_query($sql);
+ $this->data['session_viewonline'] = 0;
+ }
+ }
+ }
+
+
+ // Does the user need to change their password? If so, redirect to the
+ // ucp profile reg_details page ... of course do not redirect if we're already in the ucp
+ if (!defined('IN_ADMIN') && !defined('ADMIN_START') && $config['chg_passforce'] && !empty($this->data['is_registered']) && $auth->acl_get('u_chgpasswd') && $this->data['user_passchg'] < time() - ($config['chg_passforce'] * 86400))
+ {
+ if (strpos($this->page['query_string'], 'mode=reg_details') === false && $this->page['page_name'] != "ucp.$phpEx")
+ {
+ redirect(append_sid("{$phpbb_root_path}ucp.$phpEx", 'i=profile&amp;mode=reg_details'));
+ }
+ }
+
+ return;
+ }
+
+ /**
+ * More advanced language substitution
+ * Function to mimic sprintf() with the possibility of using phpBB's language system to substitute nullar/singular/plural forms.
+ * Params are the language key and the parameters to be substituted.
+ * This function/functionality is inspired by SHS` and Ashe.
+ *
+ * Example call: <samp>$user->lang('NUM_POSTS_IN_QUEUE', 1);</samp>
+ *
+ * If the first parameter is an array, the elements are used as keys and subkeys to get the language entry:
+ * Example: <samp>$user->lang(array('datetime', 'AGO'), 1)</samp> uses $user->lang['datetime']['AGO'] as language entry.
+ */
+ function lang()
+ {
+ $args = func_get_args();
+ $key = $args[0];
+
+ if (is_array($key))
+ {
+ $lang = &$this->lang[array_shift($key)];
+
+ foreach ($key as $_key)
+ {
+ $lang = &$lang[$_key];
+ }
+ }
+ else
+ {
+ $lang = &$this->lang[$key];
+ }
+
+ // Return if language string does not exist
+ if (!isset($lang) || (!is_string($lang) && !is_array($lang)))
+ {
+ return $key;
+ }
+
+ // If the language entry is a string, we simply mimic sprintf() behaviour
+ if (is_string($lang))
+ {
+ if (sizeof($args) == 1)
+ {
+ return $lang;
+ }
+
+ // Replace key with language entry and simply pass along...
+ $args[0] = $lang;
+ return call_user_func_array('sprintf', $args);
+ }
+ else if (sizeof($lang) == 0)
+ {
+ // If the language entry is an empty array, we just return the language key
+ return $args[0];
+ }
+
+ // It is an array... now handle different nullar/singular/plural forms
+ $key_found = false;
+
+ // We now get the first number passed and will select the key based upon this number
+ for ($i = 1, $num_args = sizeof($args); $i < $num_args; $i++)
+ {
+ if (is_int($args[$i]) || is_float($args[$i]))
+ {
+ if ($args[$i] == 0 && isset($lang[0]))
+ {
+ // We allow each translation using plural forms to specify a version for the case of 0 things,
+ // so that "0 users" may be displayed as "No users".
+ $key_found = 0;
+ break;
+ }
+ else
+ {
+ $use_plural_form = $this->get_plural_form($args[$i]);
+ if (isset($lang[$use_plural_form]))
+ {
+ // The key we should use exists, so we use it.
+ $key_found = $use_plural_form;
+ }
+ else
+ {
+ // If the key we need to use does not exist, we fall back to the previous one.
+ $numbers = array_keys($lang);
+
+ foreach ($numbers as $num)
+ {
+ if ($num > $use_plural_form)
+ {
+ break;
+ }
+
+ $key_found = $num;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ // Ok, let's check if the key was found, else use the last entry (because it is mostly the plural form)
+ if ($key_found === false)
+ {
+ $numbers = array_keys($lang);
+ $key_found = end($numbers);
+ }
+
+ // Use the language string we determined and pass it to sprintf()
+ $args[0] = $lang[$key_found];
+ return call_user_func_array('sprintf', $args);
+ }
+
+ /**
+ * Determine which plural form we should use.
+ * For some languages this is not as simple as for English.
+ *
+ * @param $number int|float The number we want to get the plural case for. Float numbers are floored.
+ * @param $force_rule mixed False to use the plural rule of the language package
+ * or an integer to force a certain plural rule
+ * @return int The plural-case we need to use for the number plural-rule combination
+ */
+ function get_plural_form($number, $force_rule = false)
+ {
+ $number = (int) $number;
+
+ // Default to English system
+ $plural_rule = ($force_rule !== false) ? $force_rule : ((isset($this->lang['PLURAL_RULE'])) ? $this->lang['PLURAL_RULE'] : 1);
+
+ return phpbb_get_plural_form($plural_rule, $number);
+ }
+
+ /**
+ * Add Language Items - use_db and use_help are assigned where needed (only use them to force inclusion)
+ *
+ * @param mixed $lang_set specifies the language entries to include
+ * @param bool $use_db internal variable for recursion, do not use
+ * @param bool $use_help internal variable for recursion, do not use
+ * @param string $ext_name The extension to load language from, or empty for core files
+ *
+ * Examples:
+ * <code>
+ * $lang_set = array('posting', 'help' => 'faq');
+ * $lang_set = array('posting', 'viewtopic', 'help' => array('bbcode', 'faq'))
+ * $lang_set = array(array('posting', 'viewtopic'), 'help' => array('bbcode', 'faq'))
+ * $lang_set = 'posting'
+ * $lang_set = array('help' => 'faq', 'db' => array('help:faq', 'posting'))
+ * </code>
+ */
+ function add_lang($lang_set, $use_db = false, $use_help = false, $ext_name = '')
+ {
+ global $phpEx;
+
+ if (is_array($lang_set))
+ {
+ foreach ($lang_set as $key => $lang_file)
+ {
+ // Please do not delete this line.
+ // We have to force the type here, else [array] language inclusion will not work
+ $key = (string) $key;
+
+ if ($key == 'db')
+ {
+ $this->add_lang($lang_file, true, $use_help, $ext_name);
+ }
+ else if ($key == 'help')
+ {
+ $this->add_lang($lang_file, $use_db, true, $ext_name);
+ }
+ else if (!is_array($lang_file))
+ {
+ $this->set_lang($this->lang, $this->help, $lang_file, $use_db, $use_help, $ext_name);
+ }
+ else
+ {
+ $this->add_lang($lang_file, $use_db, $use_help, $ext_name);
+ }
+ }
+ unset($lang_set);
+ }
+ else if ($lang_set)
+ {
+ $this->set_lang($this->lang, $this->help, $lang_set, $use_db, $use_help, $ext_name);
+ }
+ }
+
+ /**
+ * Add Language Items from an extension - use_db and use_help are assigned where needed (only use them to force inclusion)
+ *
+ * @param string $ext_name The extension to load language from, or empty for core files
+ * @param mixed $lang_set specifies the language entries to include
+ * @param bool $use_db internal variable for recursion, do not use
+ * @param bool $use_help internal variable for recursion, do not use
+ */
+ function add_lang_ext($ext_name, $lang_set, $use_db = false, $use_help = false)
+ {
+ if ($ext_name === '/')
+ {
+ $ext_name = '';
+ }
+
+ $this->add_lang($lang_set, $use_db, $use_help, $ext_name);
+ }
+
+ /**
+ * Set language entry (called by add_lang)
+ * @access private
+ */
+ function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false, $ext_name = '')
+ {
+ global $phpbb_root_path, $phpEx;
+
+ // Make sure the language name is set (if the user setup did not happen it is not set)
+ if (!$this->lang_name)
+ {
+ global $config;
+ $this->lang_name = basename($config['default_lang']);
+ }
+
+ // $lang == $this->lang
+ // $help == $this->help
+ // - add appropriate variables here, name them as they are used within the language file...
+ if (!$use_db)
+ {
+ if ($use_help && strpos($lang_file, '/') !== false)
+ {
+ $filename = dirname($lang_file) . '/help_' . basename($lang_file);
+ }
+ else
+ {
+ $filename = (($use_help) ? 'help_' : '') . $lang_file;
+ }
+
+ if ($ext_name)
+ {
+ global $phpbb_extension_manager;
+ $ext_path = $phpbb_extension_manager->get_extension_path($ext_name, true);
+
+ $lang_path = $ext_path . 'language/';
+ }
+ else
+ {
+ $lang_path = $this->lang_path;
+ }
+
+ if (strpos($phpbb_root_path . $filename, $lang_path . $this->lang_name . '/') === 0)
+ {
+ $language_filename = $phpbb_root_path . $filename;
+ }
+ else
+ {
+ $language_filename = $lang_path . $this->lang_name . '/' . $filename . '.' . $phpEx;
+ }
+
+ if (!file_exists($language_filename))
+ {
+ global $config;
+
+ if ($this->lang_name == 'en')
+ {
+ // The user's selected language is missing the file, the board default's language is missing the file, and the file doesn't exist in /en.
+ $language_filename = str_replace($lang_path . 'en', $lang_path . $this->data['user_lang'], $language_filename);
+ trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR);
+ }
+ else if ($this->lang_name == basename($config['default_lang']))
+ {
+ // Fall back to the English Language
+ $this->lang_name = 'en';
+ $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name);
+ }
+ else if ($this->lang_name == $this->data['user_lang'])
+ {
+ // Fall back to the board default language
+ $this->lang_name = basename($config['default_lang']);
+ $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name);
+ }
+
+ // Reset the lang name
+ $this->lang_name = (file_exists($lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']);
+ return;
+ }
+
+ // Do not suppress error if in DEBUG_EXTRA mode
+ $include_result = (defined('DEBUG_EXTRA')) ? (include $language_filename) : (@include $language_filename);
+
+ if ($include_result === false)
+ {
+ trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR);
+ }
+ }
+ else if ($use_db)
+ {
+ // Get Database Language Strings
+ // Put them into $lang if nothing is prefixed, put them into $help if help: is prefixed
+ // For example: help:faq, posting
+ }
+ }
+
+ /**
+ * Format user date
+ *
+ * @param int $gmepoch unix timestamp
+ * @param string $format date format in date() notation. | used to indicate relative dates, for example |d m Y|, h:i is translated to Today, h:i.
+ * @param bool $forcedate force non-relative date format.
+ *
+ * @return mixed translated date
+ */
+ function format_date($gmepoch, $format = false, $forcedate = false)
+ {
+ static $midnight;
+ static $date_cache;
+
+ $format = (!$format) ? $this->date_format : $format;
+ $now = time();
+ $delta = $now - $gmepoch;
+
+ if (!isset($date_cache[$format]))
+ {
+ // Is the user requesting a friendly date format (i.e. 'Today 12:42')?
+ $date_cache[$format] = array(
+ 'is_short' => strpos($format, '|'),
+ 'format_short' => substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1),
+ 'format_long' => str_replace('|', '', $format),
+ 'lang' => $this->lang['datetime'],
+ );
+
+ // Short representation of month in format? Some languages use different terms for the long and short format of May
+ if ((strpos($format, '\M') === false && strpos($format, 'M') !== false) || (strpos($format, '\r') === false && strpos($format, 'r') !== false))
+ {
+ $date_cache[$format]['lang']['May'] = $this->lang['datetime']['May_short'];
+ }
+ }
+
+ // Zone offset
+ $zone_offset = $this->timezone + $this->dst;
+
+ // Show date < 1 hour ago as 'xx min ago' but not greater than 60 seconds in the future
+ // A small tolerence is given for times in the future but in the same minute are displayed as '< than a minute ago'
+ if ($delta < 3600 && $delta > -60 && ($delta >= -5 || (($now / 60) % 60) == (($gmepoch / 60) % 60)) && $date_cache[$format]['is_short'] !== false && !$forcedate && isset($this->lang['datetime']['AGO']))
+ {
+ return $this->lang(array('datetime', 'AGO'), max(0, (int) floor($delta / 60)));
+ }
+
+ if (!$midnight)
+ {
+ list($d, $m, $y) = explode(' ', gmdate('j n Y', time() + $zone_offset));
+ $midnight = gmmktime(0, 0, 0, $m, $d, $y) - $zone_offset;
+ }
+
+ if ($date_cache[$format]['is_short'] !== false && !$forcedate && !($gmepoch < $midnight - 86400 || $gmepoch > $midnight + 172800))
+ {
+ $day = false;
+
+ if ($gmepoch > $midnight + 86400)
+ {
+ $day = 'TOMORROW';
+ }
+ else if ($gmepoch > $midnight)
+ {
+ $day = 'TODAY';
+ }
+ else if ($gmepoch > $midnight - 86400)
+ {
+ $day = 'YESTERDAY';
+ }
+
+ if ($day !== false)
+ {
+ return str_replace('||', $this->lang['datetime'][$day], strtr(@gmdate($date_cache[$format]['format_short'], $gmepoch + $zone_offset), $date_cache[$format]['lang']));
+ }
+ }
+
+ return strtr(@gmdate($date_cache[$format]['format_long'], $gmepoch + $zone_offset), $date_cache[$format]['lang']);
+ }
+
+ /**
+ * Get language id currently used by the user
+ */
+ function get_iso_lang_id()
+ {
+ global $config, $db;
+
+ if (!empty($this->lang_id))
+ {
+ return $this->lang_id;
+ }
+
+ if (!$this->lang_name)
+ {
+ $this->lang_name = $config['default_lang'];
+ }
+
+ $sql = 'SELECT lang_id
+ FROM ' . LANG_TABLE . "
+ WHERE lang_iso = '" . $db->sql_escape($this->lang_name) . "'";
+ $result = $db->sql_query($sql);
+ $this->lang_id = (int) $db->sql_fetchfield('lang_id');
+ $db->sql_freeresult($result);
+
+ return $this->lang_id;
+ }
+
+ /**
+ * Get users profile fields
+ */
+ function get_profile_fields($user_id)
+ {
+ global $db;
+
+ if (isset($this->profile_fields))
+ {
+ return;
+ }
+
+ $sql = 'SELECT *
+ FROM ' . PROFILE_FIELDS_DATA_TABLE . "
+ WHERE user_id = $user_id";
+ $result = $db->sql_query_limit($sql, 1);
+ $this->profile_fields = (!($row = $db->sql_fetchrow($result))) ? array() : $row;
+ $db->sql_freeresult($result);
+ }
+
+ /**
+ * Specify/Get image
+ */
+ function img($img, $alt = '')
+ {
+ $alt = (!empty($this->lang[$alt])) ? $this->lang[$alt] : $alt;
+ return '<span class="imageset ' . $img . '">' . $alt . '</span>';
+ }
+
+ /**
+ * Get option bit field from user options.
+ *
+ * @param int $key option key, as defined in $keyoptions property.
+ * @param int $data bit field value to use, or false to use $this->data['user_options']
+ * @return bool true if the option is set in the bit field, false otherwise
+ */
+ function optionget($key, $data = false)
+ {
+ $var = ($data !== false) ? $data : $this->data['user_options'];
+ return phpbb_optionget($this->keyoptions[$key], $var);
+ }
+
+ /**
+ * Set option bit field for user options.
+ *
+ * @param int $key Option key, as defined in $keyoptions property.
+ * @param bool $value True to set the option, false to clear the option.
+ * @param int $data Current bit field value, or false to use $this->data['user_options']
+ * @return int|bool If $data is false, the bit field is modified and
+ * written back to $this->data['user_options'], and
+ * return value is true if the bit field changed and
+ * false otherwise. If $data is not false, the new
+ * bitfield value is returned.
+ */
+ function optionset($key, $value, $data = false)
+ {
+ $var = ($data !== false) ? $data : $this->data['user_options'];
+
+ $new_var = phpbb_optionset($this->keyoptions[$key], $value, $var);
+
+ if ($data === false)
+ {
+ if ($new_var != $var)
+ {
+ $this->data['user_options'] = $new_var;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ return $new_var;
+ }
+ }
+
+ /**
+ * Funtion to make the user leave the NEWLY_REGISTERED system group.
+ * @access public
+ */
+ function leave_newly_registered()
+ {
+ global $db;
+
+ if (empty($this->data['user_new']))
+ {
+ return false;
+ }
+
+ if (!function_exists('remove_newly_registered'))
+ {
+ global $phpbb_root_path, $phpEx;
+
+ include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
+ }
+ if ($group = remove_newly_registered($this->data['user_id'], $this->data))
+ {
+ $this->data['group_id'] = $group;
+
+ }
+ $this->data['user_permissions'] = '';
+ $this->data['user_new'] = 0;
+
+ return true;
+ }
+
+ /**
+ * Returns all password protected forum ids the user is currently NOT authenticated for.
+ *
+ * @return array Array of forum ids
+ * @access public
+ */
+ function get_passworded_forums()
+ {
+ global $db;
+
+ $sql = 'SELECT f.forum_id, fa.user_id
+ FROM ' . FORUMS_TABLE . ' f
+ LEFT JOIN ' . FORUMS_ACCESS_TABLE . " fa
+ ON (fa.forum_id = f.forum_id
+ AND fa.session_id = '" . $db->sql_escape($this->session_id) . "')
+ WHERE f.forum_password <> ''";
+ $result = $db->sql_query($sql);
+
+ $forum_ids = array();
+ while ($row = $db->sql_fetchrow($result))
+ {
+ $forum_id = (int) $row['forum_id'];
+
+ if ($row['user_id'] != $this->data['user_id'])
+ {
+ $forum_ids[$forum_id] = $forum_id;
+ }
+ }
+ $db->sql_freeresult($result);
+
+ return $forum_ids;
+ }
+}