phpbb/phpBB/includes/acp/acp_profile.php
javiexin b1e1ee7d55 [ticket/13867] Enable/disable mechanism for new profile field types
Adds methods to enable, disable and purge profile field types to the
profilefields\manager class. These methods are to be called from
extensions that add new profile field types on the enable, disable
and purge methods of the ext class. If not done, any profile field
of a new type that is left after extension is disabled or removed will
break the forum in several places.
Remove dependency from container, add dependencies with specific classes.
Change try/catch by !isset.
Execute requested changes: more meaningful var names, json_encode, empty.
Execute requested changes: separate a utilit list function, use
sql_in_set, use single quotes ('). Remove code approved in a different PR.

PHPBB3-13867
2020-03-23 22:37:50 +01:00

1288 lines
40 KiB
PHP

<?php
/**
*
* This file is part of the phpBB Forum Software package.
*
* @copyright (c) phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
* For full copyright and license information, please see
* the docs/CREDITS.txt file.
*
*/
/**
* @ignore
*/
if (!defined('IN_PHPBB'))
{
exit;
}
class acp_profile
{
var $u_action;
var $edit_lang_id;
var $lang_defs;
/**
* @var \phpbb\di\service_collection
*/
protected $type_collection;
function main($id, $mode)
{
global $config, $db, $user, $template;
global $phpbb_root_path, $phpEx;
global $request, $phpbb_container, $phpbb_log, $phpbb_dispatcher;
if (!function_exists('generate_smilies'))
{
include($phpbb_root_path . 'includes/functions_posting.' . $phpEx);
}
if (!function_exists('user_get_id_name'))
{
include($phpbb_root_path . 'includes/functions_user.' . $phpEx);
}
$user->add_lang(array('ucp', 'acp/profile'));
$this->tpl_name = 'acp_profile';
$this->page_title = 'ACP_CUSTOM_PROFILE_FIELDS';
$field_id = $request->variable('field_id', 0);
$action = (isset($_POST['create'])) ? 'create' : $request->variable('action', '');
$error = array();
$form_key = 'acp_profile';
add_form_key($form_key);
if (!$field_id && in_array($action, array('delete','activate', 'deactivate', 'move_up', 'move_down', 'edit')))
{
trigger_error($user->lang['NO_FIELD_ID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
/* @var $cp \phpbb\profilefields\manager */
$cp = $phpbb_container->get('profilefields.manager');
$this->type_collection = $phpbb_container->get('profilefields.type_collection');
// Build Language array
// Based on this, we decide which elements need to be edited later and which language items are missing
$this->lang_defs = array();
$sql = 'SELECT lang_id, lang_iso
FROM ' . LANG_TABLE . '
ORDER BY lang_english_name';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
// Make some arrays with all available languages
$this->lang_defs['id'][$row['lang_id']] = $row['lang_iso'];
$this->lang_defs['iso'][$row['lang_iso']] = $row['lang_id'];
}
$db->sql_freeresult($result);
$sql = 'SELECT field_id, lang_id
FROM ' . PROFILE_LANG_TABLE . '
ORDER BY lang_id';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
// Which languages are available for each item
$this->lang_defs['entry'][$row['field_id']][] = $row['lang_id'];
}
$db->sql_freeresult($result);
// Have some fields been defined?
if (isset($this->lang_defs['entry']))
{
foreach ($this->lang_defs['entry'] as $field_ident => $field_ary)
{
// Fill an array with the languages that are missing for each field
$this->lang_defs['diff'][$field_ident] = array_diff(array_values($this->lang_defs['iso']), $field_ary);
}
}
switch ($action)
{
case 'delete':
if (confirm_box(true))
{
$sql = 'SELECT field_ident
FROM ' . PROFILE_FIELDS_TABLE . "
WHERE field_id = $field_id";
$result = $db->sql_query($sql);
$field_ident = (string) $db->sql_fetchfield('field_ident');
$db->sql_freeresult($result);
$db->sql_transaction('begin');
$db->sql_query('DELETE FROM ' . PROFILE_FIELDS_TABLE . " WHERE field_id = $field_id");
$db->sql_query('DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . " WHERE field_id = $field_id");
$db->sql_query('DELETE FROM ' . PROFILE_LANG_TABLE . " WHERE field_id = $field_id");
/* @var $db_tools \phpbb\db\tools\tools_interface */
$db_tools = $phpbb_container->get('dbal.tools');
$db_tools->sql_column_remove(PROFILE_FIELDS_DATA_TABLE, 'pf_' . $field_ident);
$order = 0;
$sql = 'SELECT *
FROM ' . PROFILE_FIELDS_TABLE . '
ORDER BY field_order';
$result = $db->sql_query($sql);
while ($row = $db->sql_fetchrow($result))
{
$order++;
if ($row['field_order'] != $order)
{
$sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . "
SET field_order = $order
WHERE field_id = {$row['field_id']}";
$db->sql_query($sql);
}
}
$db->sql_freeresult($result);
$db->sql_transaction('commit');
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_REMOVED', false, array($field_ident));
trigger_error($user->lang['REMOVED_PROFILE_FIELD'] . adm_back_link($this->u_action));
}
else
{
confirm_box(false, 'DELETE_PROFILE_FIELD', build_hidden_fields(array(
'i' => $id,
'mode' => $mode,
'action' => $action,
'field_id' => $field_id,
)));
}
break;
case 'activate':
if (!check_link_hash($request->variable('hash', ''), 'acp_profile'))
{
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'SELECT lang_id
FROM ' . LANG_TABLE . "
WHERE lang_iso = '" . $db->sql_escape($config['default_lang']) . "'";
$result = $db->sql_query($sql);
$default_lang_id = (int) $db->sql_fetchfield('lang_id');
$db->sql_freeresult($result);
if (!in_array($default_lang_id, $this->lang_defs['entry'][$field_id]))
{
trigger_error($user->lang['DEFAULT_LANGUAGE_NOT_FILLED'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . "
SET field_active = 1
WHERE field_id = $field_id";
$db->sql_query($sql);
$sql = 'SELECT field_ident
FROM ' . PROFILE_FIELDS_TABLE . "
WHERE field_id = $field_id";
$result = $db->sql_query($sql);
$field_ident = (string) $db->sql_fetchfield('field_ident');
$db->sql_freeresult($result);
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_ACTIVATE', false, array($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;
case 'deactivate':
if (!check_link_hash($request->variable('hash', ''), 'acp_profile'))
{
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . "
SET field_active = 0
WHERE field_id = $field_id";
$db->sql_query($sql);
$sql = 'SELECT field_ident
FROM ' . PROFILE_FIELDS_TABLE . "
WHERE field_id = $field_id";
$result = $db->sql_query($sql);
$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'),
));
}
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_DEACTIVATE', false, array($field_ident));
trigger_error($user->lang['PROFILE_FIELD_DEACTIVATED'] . adm_back_link($this->u_action));
break;
case 'move_up':
case 'move_down':
if (!check_link_hash($request->variable('hash', ''), 'acp_profile'))
{
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$sql = 'SELECT field_order
FROM ' . PROFILE_FIELDS_TABLE . "
WHERE field_id = $field_id";
$result = $db->sql_query($sql);
$field_order = $db->sql_fetchfield('field_order');
$db->sql_freeresult($result);
if ($field_order === false || ($field_order == 0 && $action == 'move_up'))
{
break;
}
$field_order = (int) $field_order;
$order_total = $field_order * 2 + (($action == 'move_up') ? -1 : 1);
$sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . "
SET field_order = $order_total - field_order
WHERE field_order IN ($field_order, " . (($action == 'move_up') ? $field_order - 1 : $field_order + 1) . ')';
$db->sql_query($sql);
if ($request->is_ajax())
{
$json_response = new \phpbb\json_response;
$json_response->send(array(
'success' => (bool) $db->sql_affectedrows(),
));
}
break;
case 'create':
case 'edit':
$step = $request->variable('step', 1);
$submit = (isset($_REQUEST['next']) || isset($_REQUEST['prev'])) ? true : false;
$save = (isset($_REQUEST['save'])) ? true : false;
// The language id of default language
$this->edit_lang_id = $this->lang_defs['iso'][$config['default_lang']];
// We are editing... we need to grab basic things
if ($action == 'edit')
{
$sql = 'SELECT l.*, f.*
FROM ' . PROFILE_LANG_TABLE . ' l, ' . PROFILE_FIELDS_TABLE . ' f
WHERE l.lang_id = ' . $this->edit_lang_id . "
AND f.field_id = $field_id
AND l.field_id = f.field_id";
$result = $db->sql_query($sql);
$field_row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
if (!$field_row)
{
// Some admin changed the default language?
$sql = 'SELECT l.*, f.*
FROM ' . PROFILE_LANG_TABLE . ' l, ' . PROFILE_FIELDS_TABLE . ' f
WHERE l.lang_id <> ' . $this->edit_lang_id . "
AND f.field_id = $field_id
AND l.field_id = f.field_id";
$result = $db->sql_query($sql);
$field_row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
if (!$field_row)
{
trigger_error($user->lang['FIELD_NOT_FOUND'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$this->edit_lang_id = $field_row['lang_id'];
}
$field_type = $field_row['field_type'];
$profile_field = $this->type_collection[$field_type];
// Get language entries
$sql = 'SELECT *
FROM ' . PROFILE_FIELDS_LANG_TABLE . '
WHERE lang_id = ' . $this->edit_lang_id . "
AND field_id = $field_id
ORDER BY option_id ASC";
$result = $db->sql_query($sql);
$lang_options = array();
while ($row = $db->sql_fetchrow($result))
{
$lang_options[$row['option_id']] = $row['lang_value'];
}
$db->sql_freeresult($result);
$s_hidden_fields = '<input type="hidden" name="field_id" value="' . $field_id . '" />';
}
else
{
// We are adding a new field, define basic params
$lang_options = $field_row = array();
$field_type = $request->variable('field_type', '');
if (!isset($this->type_collection[$field_type]))
{
trigger_error($user->lang['NO_FIELD_TYPE'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$profile_field = $this->type_collection[$field_type];
$field_row = array_merge($profile_field->get_default_option_values(), array(
'field_ident' => str_replace(' ', '_', utf8_clean_string($request->variable('field_ident', '', true))),
'field_required' => 0,
'field_show_novalue'=> 0,
'field_hide' => 0,
'field_show_profile'=> 0,
'field_no_view' => 0,
'field_show_on_reg' => 0,
'field_show_on_pm' => 0,
'field_show_on_vt' => 0,
'field_show_on_ml' => 0,
'field_is_contact' => 0,
'field_contact_desc'=> '',
'field_contact_url' => '',
'lang_name' => $request->variable('field_ident', '', true),
'lang_explain' => '',
'lang_default_value'=> '')
);
$s_hidden_fields = '<input type="hidden" name="field_type" value="' . $field_type . '" />';
}
// $exclude contains the data we gather in each step
$exclude = array(
1 => array('field_ident', 'lang_name', 'lang_explain', 'field_option_none', 'field_show_on_reg', 'field_show_on_pm', 'field_show_on_vt', 'field_show_on_ml', 'field_required', 'field_show_novalue', 'field_hide', 'field_show_profile', 'field_no_view', 'field_is_contact', 'field_contact_desc', 'field_contact_url'),
2 => array('field_length', 'field_maxlen', 'field_minlen', 'field_validation', 'field_novalue', 'field_default_value'),
3 => array('l_lang_name', 'l_lang_explain', 'l_lang_default_value', 'l_lang_options')
);
// Visibility Options...
$visibility_ary = array(
'field_required',
'field_show_novalue',
'field_show_on_reg',
'field_show_on_pm',
'field_show_on_vt',
'field_show_on_ml',
'field_show_profile',
'field_hide',
'field_is_contact',
);
/**
* Event to add initialization for new profile field table fields
*
* @event core.acp_profile_create_edit_init
* @var string action create|edit
* @var int step Configuration step (1|2|3)
* @var bool submit Form has been submitted
* @var bool save Configuration should be saved
* @var string field_type Type of the field we are dealing with
* @var array field_row Array of data about the field
* @var array exclude Array of excluded fields by step
* @var array visibility_ary Array of fields that are visibility related
* @since 3.1.6-RC1
*/
$vars = array(
'action',
'step',
'submit',
'save',
'field_type',
'field_row',
'exclude',
'visibility_ary',
);
extract($phpbb_dispatcher->trigger_event('core.acp_profile_create_edit_init', compact($vars)));
$options = $profile_field->prepare_options_form($exclude, $visibility_ary);
$cp->vars['field_ident'] = ($action == 'create' && $step == 1) ? utf8_clean_string($request->variable('field_ident', $field_row['field_ident'], true)) : $request->variable('field_ident', $field_row['field_ident']);
$cp->vars['lang_name'] = $request->variable('lang_name', $field_row['lang_name'], true);
$cp->vars['lang_explain'] = $request->variable('lang_explain', $field_row['lang_explain'], true);
$cp->vars['lang_default_value'] = $request->variable('lang_default_value', $field_row['lang_default_value'], true);
$cp->vars['field_contact_desc'] = $request->variable('field_contact_desc', $field_row['field_contact_desc'], true);
$cp->vars['field_contact_url'] = $request->variable('field_contact_url', $field_row['field_contact_url'], true);
foreach ($visibility_ary as $val)
{
$cp->vars[$val] = ($submit || $save) ? $request->variable($val, 0) : $field_row[$val];
}
$cp->vars['field_no_view'] = $request->variable('field_no_view', (int) $field_row['field_no_view']);
// If the user has submitted a form with options (i.e. dropdown field)
if ($options)
{
$exploded_options = (is_array($options)) ? $options : explode("\n", $options);
if (count($exploded_options) == count($lang_options) || $action == 'create')
{
// The number of options in the field is equal to the number of options already in the database
// Or we are creating a new dropdown list.
$cp->vars['lang_options'] = $exploded_options;
}
else if ($action == 'edit')
{
// Changing the number of options? (We remove and re-create the option fields)
$cp->vars['lang_options'] = $exploded_options;
}
}
else
{
$cp->vars['lang_options'] = $lang_options;
}
// step 2
foreach ($exclude[2] as $key)
{
$var = $request->variable($key, $field_row[$key], true);
$field_data = $cp->vars;
$var = $profile_field->get_excluded_options($key, $action, $var, $field_data, 2);
$cp->vars = $field_data;
$cp->vars[$key] = $var;
}
// step 3 - all arrays
if ($action == 'edit')
{
// Get language entries
$sql = 'SELECT *
FROM ' . PROFILE_FIELDS_LANG_TABLE . '
WHERE lang_id <> ' . $this->edit_lang_id . "
AND field_id = $field_id
ORDER BY option_id ASC";
$result = $db->sql_query($sql);
$l_lang_options = array();
while ($row = $db->sql_fetchrow($result))
{
$l_lang_options[$row['lang_id']][$row['option_id']] = $row['lang_value'];
}
$db->sql_freeresult($result);
$sql = 'SELECT lang_id, lang_name, lang_explain, lang_default_value
FROM ' . PROFILE_LANG_TABLE . '
WHERE lang_id <> ' . $this->edit_lang_id . "
AND field_id = $field_id
ORDER BY lang_id ASC";
$result = $db->sql_query($sql);
$l_lang_name = $l_lang_explain = $l_lang_default_value = array();
while ($row = $db->sql_fetchrow($result))
{
$l_lang_name[$row['lang_id']] = $row['lang_name'];
$l_lang_explain[$row['lang_id']] = $row['lang_explain'];
$l_lang_default_value[$row['lang_id']] = $row['lang_default_value'];
}
$db->sql_freeresult($result);
}
foreach ($exclude[3] as $key)
{
$cp->vars[$key] = $request->variable($key, array(0 => ''), true);
if (!$cp->vars[$key] && $action == 'edit')
{
$cp->vars[$key] = ${$key};
}
$field_data = $cp->vars;
$var = $profile_field->get_excluded_options($key, $action, $var, $field_data, 3);
$cp->vars = $field_data;
}
// Check for general issues in every step
if ($submit) // && $step == 1
{
// Check values for step 1
if ($cp->vars['field_ident'] == '')
{
$error[] = $user->lang['EMPTY_FIELD_IDENT'];
}
if (!preg_match('/^[a-z_]+$/', $cp->vars['field_ident']))
{
$error[] = $user->lang['INVALID_CHARS_FIELD_IDENT'];
}
if (strlen($cp->vars['field_ident']) > 17)
{
$error[] = $user->lang['INVALID_FIELD_IDENT_LEN'];
}
if ($cp->vars['lang_name'] == '')
{
$error[] = $user->lang['EMPTY_USER_FIELD_NAME'];
}
$error = $profile_field->validate_options_on_submit($error, $cp->vars);
// Check for already existing field ident
if ($action != 'edit')
{
$sql = 'SELECT field_ident
FROM ' . PROFILE_FIELDS_TABLE . "
WHERE field_ident = '" . $db->sql_escape($cp->vars['field_ident']) . "'";
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
if ($row)
{
$error[] = $user->lang['FIELD_IDENT_ALREADY_EXIST'];
}
}
}
if (count($error))
{
$submit = false;
}
else
{
$step = (isset($_REQUEST['next'])) ? $step + 1 : ((isset($_REQUEST['prev'])) ? $step - 1 : $step);
}
// Build up the specific hidden fields
foreach ($exclude as $num => $key_ary)
{
if ($num == $step)
{
continue;
}
$_new_key_ary = array();
$field_data = $cp->vars;
foreach ($key_ary as $key)
{
$var = $profile_field->prepare_hidden_fields($step, $key, $action, $field_data);
if ($var !== null)
{
$_new_key_ary[$key] = $var;
}
}
$cp->vars = $field_data;
$s_hidden_fields .= build_hidden_fields($_new_key_ary);
}
if (!count($error))
{
if (($step == 3 && (count($this->lang_defs['iso']) == 1 || $save)) || ($action == 'edit' && $save))
{
if (!check_form_key($form_key))
{
trigger_error($user->lang['FORM_INVALID'] . adm_back_link($this->u_action), E_USER_WARNING);
}
$this->save_profile_field($cp, $field_type, $action);
}
}
$template->assign_vars(array(
'S_EDIT' => true,
'S_EDIT_MODE' => ($action == 'edit') ? true : false,
'ERROR_MSG' => (count($error)) ? implode('<br />', $error) : '',
'L_TITLE' => $user->lang['STEP_' . $step . '_TITLE_' . strtoupper($action)],
'L_EXPLAIN' => $user->lang['STEP_' . $step . '_EXPLAIN_' . strtoupper($action)],
'U_ACTION' => $this->u_action . "&amp;action=$action&amp;step=$step",
'U_BACK' => $this->u_action)
);
// Now go through the steps
switch ($step)
{
// Create basic options - only small differences between field types
case 1:
$template_vars = array(
'S_STEP_ONE' => true,
'S_FIELD_REQUIRED' => ($cp->vars['field_required']) ? true : false,
'S_FIELD_SHOW_NOVALUE'=> ($cp->vars['field_show_novalue']) ? true : false,
'S_SHOW_ON_REG' => ($cp->vars['field_show_on_reg']) ? true : false,
'S_SHOW_ON_PM' => ($cp->vars['field_show_on_pm']) ? true : false,
'S_SHOW_ON_VT' => ($cp->vars['field_show_on_vt']) ? true : false,
'S_SHOW_ON_MEMBERLIST'=> ($cp->vars['field_show_on_ml']) ? true : false,
'S_FIELD_HIDE' => ($cp->vars['field_hide']) ? true : false,
'S_SHOW_PROFILE' => ($cp->vars['field_show_profile']) ? true : false,
'S_FIELD_NO_VIEW' => ($cp->vars['field_no_view']) ? true : false,
'S_FIELD_CONTACT' => $cp->vars['field_is_contact'],
'FIELD_CONTACT_DESC'=> $cp->vars['field_contact_desc'],
'FIELD_CONTACT_URL' => $cp->vars['field_contact_url'],
'L_LANG_SPECIFIC' => sprintf($user->lang['LANG_SPECIFIC_OPTIONS'], $config['default_lang']),
'FIELD_TYPE' => $profile_field->get_name(),
'FIELD_IDENT' => $cp->vars['field_ident'],
'LANG_NAME' => $cp->vars['lang_name'],
'LANG_EXPLAIN' => $cp->vars['lang_explain'],
);
$field_data = $cp->vars;
$profile_field->display_options($template_vars, $field_data);
$cp->vars = $field_data;
// Build common create options
$template->assign_vars($template_vars);
break;
case 2:
$template->assign_vars(array(
'S_STEP_TWO' => true,
'L_NEXT_STEP' => (count($this->lang_defs['iso']) == 1) ? $user->lang['SAVE'] : $user->lang['PROFILE_LANG_OPTIONS'])
);
// Build options based on profile type
$options = $profile_field->get_options($this->lang_defs['iso'][$config['default_lang']], $cp->vars);
foreach ($options as $num => $option_ary)
{
$template->assign_block_vars('option', $option_ary);
}
break;
// Define remaining language variables
case 3:
$template->assign_var('S_STEP_THREE', true);
$options = $this->build_language_options($cp, $field_type, $action);
foreach ($options as $lang_id => $lang_ary)
{
$template->assign_block_vars('options', array(
'LANGUAGE' => sprintf($user->lang[(($lang_id == $this->edit_lang_id) ? 'DEFAULT_' : '') . 'ISO_LANGUAGE'], $lang_ary['lang_iso']))
);
foreach ($lang_ary['fields'] as $field_ident => $field_ary)
{
$template->assign_block_vars('options.field', array(
'L_TITLE' => $field_ary['TITLE'],
'L_EXPLAIN' => (isset($field_ary['EXPLAIN'])) ? $field_ary['EXPLAIN'] : '',
'FIELD' => $field_ary['FIELD'])
);
}
}
break;
}
$field_data = $cp->vars;
/**
* Event to add template variables for new profile field table fields
*
* @event core.acp_profile_create_edit_after
* @var string action create|edit
* @var int step Configuration step (1|2|3)
* @var bool submit Form has been submitted
* @var bool save Configuration should be saved
* @var string field_type Type of the field we are dealing with
* @var array field_data Array of data about the field
* @var array s_hidden_fields Array of hidden fields in case this needs modification
* @var array options Array of options specific to this step
* @since 3.1.6-RC1
*/
$vars = array(
'action',
'step',
'submit',
'save',
'field_type',
'field_data',
's_hidden_fields',
'options',
);
extract($phpbb_dispatcher->trigger_event('core.acp_profile_create_edit_after', compact($vars)));
$template->assign_vars(array(
'S_HIDDEN_FIELDS' => $s_hidden_fields)
);
return;
break;
}
$tpl_name = $this->tpl_name;
$page_title = $this->page_title;
$u_action = $this->u_action;
/**
* Event to handle actions on the ACP profile fields page
*
* @event core.acp_profile_action
* @var string action Action that is being performed
* @var string tpl_name Template file to load
* @var string page_title Page title
* @var string u_action The URL we are at, read only
* @since 3.2.2-RC1
*/
$vars = array(
'action',
'tpl_name',
'page_title',
'u_action',
);
extract($phpbb_dispatcher->trigger_event('core.acp_profile_action', compact($vars)));
$this->tpl_name = $tpl_name;
$this->page_title = $page_title;
unset($u_action);
$sql = 'SELECT *
FROM ' . PROFILE_FIELDS_TABLE . '
ORDER BY field_order';
$result = $db->sql_query($sql);
$s_one_need_edit = false;
while ($row = $db->sql_fetchrow($result))
{
$active_lang = (!$row['field_active']) ? 'ACTIVATE' : 'DEACTIVATE';
$active_value = (!$row['field_active']) ? 'activate' : 'deactivate';
$id = $row['field_id'];
$s_need_edit = (count($this->lang_defs['diff'][$row['field_id']])) ? true : false;
if ($s_need_edit)
{
$s_one_need_edit = true;
}
$profile_field = $this->type_collection[$row['field_type']];
$field_block = array(
'FIELD_IDENT' => $row['field_ident'],
'FIELD_TYPE' => $profile_field->get_name(),
'L_ACTIVATE_DEACTIVATE' => $user->lang[$active_lang],
'U_ACTIVATE_DEACTIVATE' => $this->u_action . "&amp;action=$active_value&amp;field_id=$id" . '&amp;hash=' . generate_link_hash('acp_profile'),
'U_EDIT' => $this->u_action . "&amp;action=edit&amp;field_id=$id",
'U_TRANSLATE' => $this->u_action . "&amp;action=edit&amp;field_id=$id&amp;step=3",
'U_DELETE' => $this->u_action . "&amp;action=delete&amp;field_id=$id",
'U_MOVE_UP' => $this->u_action . "&amp;action=move_up&amp;field_id=$id" . '&amp;hash=' . generate_link_hash('acp_profile'),
'U_MOVE_DOWN' => $this->u_action . "&amp;action=move_down&amp;field_id=$id" . '&amp;hash=' . generate_link_hash('acp_profile'),
'S_NEED_EDIT' => $s_need_edit,
);
/**
* Event to modify profile field data before it is assigned to the template
*
* @event core.acp_profile_modify_profile_row
* @var array row Array with data for the current profile field
* @var array field_block Template data that is being assigned to the 'fields' block
* @var object profile_field A profile field instance, implements \phpbb\profilefields\type\type_base
* @since 3.2.2-RC1
*/
$vars = array(
'row',
'field_block',
'profile_field',
);
extract($phpbb_dispatcher->trigger_event('core.acp_profile_modify_profile_row', compact($vars)));
$template->assign_block_vars('fields', $field_block);
}
$db->sql_freeresult($result);
// At least one option field needs editing?
if ($s_one_need_edit)
{
$template->assign_var('S_NEED_EDIT', true);
}
$s_select_type = '';
foreach ($this->type_collection as $key => $profile_field)
{
$s_select_type .= '<option value="' . $key . '">' . $profile_field->get_name() . '</option>';
}
$template->assign_vars(array(
'U_ACTION' => $this->u_action,
'S_TYPE_OPTIONS' => $s_select_type,
));
}
/**
* Build all Language specific options
*/
function build_language_options($cp, $field_type, $action = 'create')
{
global $user, $config, $db, $request;
$default_lang_id = (!empty($this->edit_lang_id)) ? $this->edit_lang_id : $this->lang_defs['iso'][$config['default_lang']];
$sql = 'SELECT lang_id, lang_iso
FROM ' . LANG_TABLE . '
WHERE lang_id <> ' . (int) $default_lang_id . '
ORDER BY lang_english_name';
$result = $db->sql_query($sql);
$languages = array();
while ($row = $db->sql_fetchrow($result))
{
$languages[$row['lang_id']] = $row['lang_iso'];
}
$db->sql_freeresult($result);
$profile_field = $this->type_collection[$field_type];
$options = $profile_field->get_language_options($cp->vars);
$lang_options = array();
foreach ($options as $field => $field_type)
{
$lang_options[1]['lang_iso'] = $this->lang_defs['id'][$default_lang_id];
$lang_options[1]['fields'][$field] = array(
'TITLE' => $user->lang['CP_' . strtoupper($field)],
'FIELD' => '<dd>' . ((is_array($cp->vars[$field])) ? implode('<br />', $cp->vars[$field]) : bbcode_nl2br($cp->vars[$field])) . '</dd>'
);
if (isset($user->lang['CP_' . strtoupper($field) . '_EXPLAIN']))
{
$lang_options[1]['fields'][$field]['EXPLAIN'] = $user->lang['CP_' . strtoupper($field) . '_EXPLAIN'];
}
}
foreach ($languages as $lang_id => $lang_iso)
{
$lang_options[$lang_id]['lang_iso'] = $lang_iso;
foreach ($options as $field => $field_type)
{
$value = ($action == 'create') ? $request->variable('l_' . $field, array(0 => ''), true) : $cp->vars['l_' . $field];
if ($field == 'lang_options')
{
$var = (!isset($cp->vars['l_lang_options'][$lang_id]) || !is_array($cp->vars['l_lang_options'][$lang_id])) ? $cp->vars['lang_options'] : $cp->vars['l_lang_options'][$lang_id];
switch ($field_type)
{
case 'two_options':
$lang_options[$lang_id]['fields'][$field] = array(
'TITLE' => $user->lang['CP_' . strtoupper($field)],
'FIELD' => '
<dd><input class="medium" name="l_' . $field . '[' . $lang_id . '][]" value="' . ((isset($value[$lang_id][0])) ? $value[$lang_id][0] : $var[0]) . '" /> ' . $user->lang['FIRST_OPTION'] . '</dd>
<dd><input class="medium" name="l_' . $field . '[' . $lang_id . '][]" value="' . ((isset($value[$lang_id][1])) ? $value[$lang_id][1] : $var[1]) . '" /> ' . $user->lang['SECOND_OPTION'] . '</dd>'
);
break;
case 'optionfield':
$value = ((isset($value[$lang_id])) ? ((is_array($value[$lang_id])) ? implode("\n", $value[$lang_id]) : $value[$lang_id]) : implode("\n", $var));
$lang_options[$lang_id]['fields'][$field] = array(
'TITLE' => $user->lang['CP_' . strtoupper($field)],
'FIELD' => '<dd><textarea name="l_' . $field . '[' . $lang_id . ']" rows="7" cols="80">' . $value . '</textarea></dd>'
);
break;
}
if (isset($user->lang['CP_' . strtoupper($field) . '_EXPLAIN']))
{
$lang_options[$lang_id]['fields'][$field]['EXPLAIN'] = $user->lang['CP_' . strtoupper($field) . '_EXPLAIN'];
}
}
else
{
$var = ($action == 'create' || !is_array($cp->vars[$field])) ? $cp->vars[$field] : $cp->vars[$field][$lang_id];
$lang_options[$lang_id]['fields'][$field] = array(
'TITLE' => $user->lang['CP_' . strtoupper($field)],
'FIELD' => ($field_type == 'string') ? '<dd><input class="medium" type="text" name="l_' . $field . '[' . $lang_id . ']" value="' . ((isset($value[$lang_id])) ? $value[$lang_id] : $var) . '" /></dd>' : '<dd><textarea name="l_' . $field . '[' . $lang_id . ']" rows="3" cols="80">' . ((isset($value[$lang_id])) ? $value[$lang_id] : $var) . '</textarea></dd>'
);
if (isset($user->lang['CP_' . strtoupper($field) . '_EXPLAIN']))
{
$lang_options[$lang_id]['fields'][$field]['EXPLAIN'] = $user->lang['CP_' . strtoupper($field) . '_EXPLAIN'];
}
}
}
}
return $lang_options;
}
/**
* Save Profile Field
*/
function save_profile_field($cp, $field_type, $action = 'create')
{
global $db, $config, $user, $phpbb_container, $phpbb_log, $request, $phpbb_dispatcher;
$field_id = $request->variable('field_id', 0);
// Collect all information, if something is going wrong, abort the operation
$profile_sql = $profile_lang = $empty_lang = $profile_lang_fields = array();
$default_lang_id = (!empty($this->edit_lang_id)) ? $this->edit_lang_id : $this->lang_defs['iso'][$config['default_lang']];
if ($action == 'create')
{
$sql = 'SELECT MAX(field_order) as max_field_order
FROM ' . PROFILE_FIELDS_TABLE;
$result = $db->sql_query($sql);
$new_field_order = (int) $db->sql_fetchfield('max_field_order');
$db->sql_freeresult($result);
$field_ident = $cp->vars['field_ident'];
}
// Save the field
$profile_fields = array(
'field_length' => $cp->vars['field_length'],
'field_minlen' => $cp->vars['field_minlen'],
'field_maxlen' => $cp->vars['field_maxlen'],
'field_novalue' => $cp->vars['field_novalue'],
'field_default_value' => $cp->vars['field_default_value'],
'field_validation' => $cp->vars['field_validation'],
'field_required' => $cp->vars['field_required'],
'field_show_novalue' => $cp->vars['field_show_novalue'],
'field_show_on_reg' => $cp->vars['field_show_on_reg'],
'field_show_on_pm' => $cp->vars['field_show_on_pm'],
'field_show_on_vt' => $cp->vars['field_show_on_vt'],
'field_show_on_ml' => $cp->vars['field_show_on_ml'],
'field_hide' => $cp->vars['field_hide'],
'field_show_profile' => $cp->vars['field_show_profile'],
'field_no_view' => $cp->vars['field_no_view'],
'field_is_contact' => $cp->vars['field_is_contact'],
'field_contact_desc' => $cp->vars['field_contact_desc'],
'field_contact_url' => $cp->vars['field_contact_url'],
);
$field_data = $cp->vars;
/**
* Event to modify profile field configuration data before saving to database
*
* @event core.acp_profile_create_edit_save_before
* @var string action create|edit
* @var string field_type Type of the field we are dealing with
* @var array field_data Array of data about the field
* @var array profile_fields Array of fields to be sent to the database
* @since 3.1.6-RC1
*/
$vars = array(
'action',
'field_type',
'field_data',
'profile_fields',
);
extract($phpbb_dispatcher->trigger_event('core.acp_profile_create_edit_save_before', compact($vars)));
if ($action == 'create')
{
$profile_fields += array(
'field_type' => $field_type,
'field_ident' => $field_ident,
'field_name' => $field_ident,
'field_order' => $new_field_order + 1,
'field_active' => 1
);
$sql = 'INSERT INTO ' . PROFILE_FIELDS_TABLE . ' ' . $db->sql_build_array('INSERT', $profile_fields);
$db->sql_query($sql);
$field_id = $db->sql_nextid();
}
else
{
$sql = 'UPDATE ' . PROFILE_FIELDS_TABLE . '
SET ' . $db->sql_build_array('UPDATE', $profile_fields) . "
WHERE field_id = $field_id";
$db->sql_query($sql);
}
$profile_field = $this->type_collection[$field_type];
if ($action == 'create')
{
$field_ident = 'pf_' . $field_ident;
/* @var $db_tools \phpbb\db\tools\tools_interface */
$db_tools = $phpbb_container->get('dbal.tools');
$db_tools->sql_column_add(PROFILE_FIELDS_DATA_TABLE, $field_ident, array($profile_field->get_database_column_type(), null));
}
$sql_ary = array(
'lang_name' => $cp->vars['lang_name'],
'lang_explain' => $cp->vars['lang_explain'],
'lang_default_value' => $cp->vars['lang_default_value']
);
if ($action == 'create')
{
$sql_ary['field_id'] = $field_id;
$sql_ary['lang_id'] = $default_lang_id;
$profile_sql[] = 'INSERT INTO ' . PROFILE_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
}
else
{
$this->update_insert(PROFILE_LANG_TABLE, $sql_ary, array('field_id' => $field_id, 'lang_id' => $default_lang_id));
}
if (is_array($cp->vars['l_lang_name']) && count($cp->vars['l_lang_name']))
{
foreach ($cp->vars['l_lang_name'] as $lang_id => $data)
{
if (($cp->vars['lang_name'] != '' && $cp->vars['l_lang_name'][$lang_id] == '')
|| ($cp->vars['lang_explain'] != '' && $cp->vars['l_lang_explain'][$lang_id] == '')
|| ($cp->vars['lang_default_value'] != '' && $cp->vars['l_lang_default_value'][$lang_id] == ''))
{
$empty_lang[$lang_id] = true;
break;
}
if (!isset($empty_lang[$lang_id]))
{
$profile_lang[] = array(
'field_id' => $field_id,
'lang_id' => $lang_id,
'lang_name' => $cp->vars['l_lang_name'][$lang_id],
'lang_explain' => (isset($cp->vars['l_lang_explain'][$lang_id])) ? $cp->vars['l_lang_explain'][$lang_id] : '',
'lang_default_value' => (isset($cp->vars['l_lang_default_value'][$lang_id])) ? $cp->vars['l_lang_default_value'][$lang_id] : ''
);
}
}
foreach ($empty_lang as $lang_id => $NULL)
{
$sql = 'DELETE FROM ' . PROFILE_LANG_TABLE . "
WHERE field_id = $field_id
AND lang_id = " . (int) $lang_id;
$db->sql_query($sql);
}
}
$cp->vars = $profile_field->get_language_options_input($cp->vars);
if ($cp->vars['lang_options'])
{
if (!is_array($cp->vars['lang_options']))
{
$cp->vars['lang_options'] = explode("\n", $cp->vars['lang_options']);
}
if ($action != 'create')
{
$sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . "
WHERE field_id = $field_id
AND lang_id = " . (int) $default_lang_id;
$db->sql_query($sql);
}
foreach ($cp->vars['lang_options'] as $option_id => $value)
{
$sql_ary = array(
'field_type' => $field_type,
'lang_value' => $value
);
if ($action == 'create')
{
$sql_ary['field_id'] = $field_id;
$sql_ary['lang_id'] = $default_lang_id;
$sql_ary['option_id'] = (int) $option_id;
$profile_sql[] = 'INSERT INTO ' . PROFILE_FIELDS_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql_ary);
}
else
{
$this->update_insert(PROFILE_FIELDS_LANG_TABLE, $sql_ary, array(
'field_id' => $field_id,
'lang_id' => (int) $default_lang_id,
'option_id' => (int) $option_id)
);
}
}
}
if (is_array($cp->vars['l_lang_options']) && count($cp->vars['l_lang_options']))
{
$empty_lang = array();
foreach ($cp->vars['l_lang_options'] as $lang_id => $lang_ary)
{
if (!is_array($lang_ary))
{
$lang_ary = explode("\n", $lang_ary);
}
if (count($lang_ary) != count($cp->vars['lang_options']))
{
$empty_lang[$lang_id] = true;
}
if (!isset($empty_lang[$lang_id]))
{
if ($action != 'create')
{
$sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . "
WHERE field_id = $field_id
AND lang_id = " . (int) $lang_id;
$db->sql_query($sql);
}
foreach ($lang_ary as $option_id => $value)
{
$profile_lang_fields[] = array(
'field_id' => (int) $field_id,
'lang_id' => (int) $lang_id,
'option_id' => (int) $option_id,
'field_type' => $field_type,
'lang_value' => $value
);
}
}
}
foreach ($empty_lang as $lang_id => $NULL)
{
$sql = 'DELETE FROM ' . PROFILE_FIELDS_LANG_TABLE . "
WHERE field_id = $field_id
AND lang_id = " . (int) $lang_id;
$db->sql_query($sql);
}
}
foreach ($profile_lang as $sql)
{
if ($action == 'create')
{
$profile_sql[] = 'INSERT INTO ' . PROFILE_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql);
}
else
{
$lang_id = $sql['lang_id'];
unset($sql['lang_id'], $sql['field_id']);
$this->update_insert(PROFILE_LANG_TABLE, $sql, array('lang_id' => (int) $lang_id, 'field_id' => $field_id));
}
}
if (count($profile_lang_fields))
{
foreach ($profile_lang_fields as $sql)
{
if ($action == 'create')
{
$profile_sql[] = 'INSERT INTO ' . PROFILE_FIELDS_LANG_TABLE . ' ' . $db->sql_build_array('INSERT', $sql);
}
else
{
$lang_id = $sql['lang_id'];
$option_id = $sql['option_id'];
unset($sql['lang_id'], $sql['field_id'], $sql['option_id']);
$this->update_insert(PROFILE_FIELDS_LANG_TABLE, $sql, array(
'lang_id' => $lang_id,
'field_id' => $field_id,
'option_id' => $option_id)
);
}
}
}
$db->sql_transaction('begin');
if ($action == 'create')
{
foreach ($profile_sql as $sql)
{
$db->sql_query($sql);
}
}
$db->sql_transaction('commit');
if ($action == 'edit')
{
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_EDIT', false, array($cp->vars['field_ident'] . ':' . $cp->vars['lang_name']));
trigger_error($user->lang['CHANGED_PROFILE_FIELD'] . adm_back_link($this->u_action));
}
else
{
$phpbb_log->add('admin', $user->data['user_id'], $user->ip, 'LOG_PROFILE_FIELD_CREATE', false, array(substr($field_ident, 3) . ':' . $cp->vars['lang_name']));
trigger_error($user->lang['ADDED_PROFILE_FIELD'] . adm_back_link($this->u_action));
}
}
/**
* Update, then insert if not successfull
*/
function update_insert($table, $sql_ary, $where_fields)
{
global $db;
$where_sql = array();
$check_key = '';
foreach ($where_fields as $key => $value)
{
$check_key = (!$check_key) ? $key : $check_key;
$where_sql[] = $key . ' = ' . ((is_string($value)) ? "'" . $db->sql_escape($value) . "'" : (int) $value);
}
if (!count($where_sql))
{
return;
}
$sql = "SELECT $check_key
FROM $table
WHERE " . implode(' AND ', $where_sql);
$result = $db->sql_query($sql);
$row = $db->sql_fetchrow($result);
$db->sql_freeresult($result);
if (!$row)
{
$sql_ary = array_merge($where_fields, $sql_ary);
if (count($sql_ary))
{
$db->sql_query("INSERT INTO $table " . $db->sql_build_array('INSERT', $sql_ary));
}
}
else
{
if (count($sql_ary))
{
$sql = "UPDATE $table SET " . $db->sql_build_array('UPDATE', $sql_ary) . '
WHERE ' . implode(' AND ', $where_sql);
$db->sql_query($sql);
}
}
}
}