| Server IP : 54.36.91.62 / Your IP : 216.73.217.112 Web Server : Apache System : Linux webm013.cluster127.gra.hosting.ovh.net 5.15.206-ovh-vps-grsec-zfs-classid #1 SMP Fri May 15 02:41:25 UTC 2026 x86_64 User : coopiak ( 151928) PHP Version : 8.3.23 Disable Function : _dyuweyrj4,_dyuweyrj4r,dl MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : ON | Sudo : OFF | Pkexec : OFF Directory : /home/coopiak/amisdesseniors-fr/nice/libraries/CBLib/CB/Legacy/ |
Upload File : |
<?php
/**
* CBLib, Community Builder Library(TM)
* @version $Id: 6/18/14 2:27 PM $
* @copyright (C) 2004-2025 www.joomlapolis.com / Lightning MultiCom SA - and its licensors, all rights reserved
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU/GPL version 2
*/
use CBLib\Application\Application;
use CBLib\Database\DatabaseUpgrade;
use CBLib\Language\CBTxt;
use CBLib\Registry\Registry;
use CBLib\Xml\SimpleXMLElement;
use CB\Database\Table\FieldTable;
use CB\Database\Table\PluginTable;
use CB\Database\Table\UserTable;
use CBLib\Registry\GetterInterface;
defined('CBLIB') or die();
/**
* cbFieldHandler Class implementation
* Field Class for handling the CB field api
*/
class cbFieldHandler extends cbPluginHandler
{
/**
* Plugin of this field
* @var PluginTable
*/
private $_plugin = null;
/**
* XML of the Plugin of this field
* @var SimpleXMLElement
*/
private $_xml = null;
/**
* XML of this field
* @var SimpleXMLElement
*/
private $_fieldXml = null;
/**
* Constructor (needed for PHP 7 so that we can keep the old PHP4-type constructor until CB 3.0)
*/
public function __construct()
{
parent::__construct();
}
/**
* Constructor named old-fashion for backwards compatibility reason
* until all classes extending cbFieldHandler call parent::__construct() instead of $this->cbFieldHandler()
* @deprecated 2.0 use parent::__construct() instead.
*/
public function cbFieldHandler( )
{
self::__construct();
}
/**
* Overridable methods:
*/
/**
* Initializer:
* Puts the default value of $field into $user (for registration or new user in backend)
*
* @param FieldTable $field
* @param UserTable $user
* @param string $reason 'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
*/
public function initFieldToDefault( &$field, &$user, $reason )
{
foreach ( $field->getTableColumns() as $col ) {
if ( $reason == 'search' ) {
$user->$col = null;
} else {
$user->$col = $field->default;
}
}
}
/**
* Formatter:
* Returns a field in specified format
*
* @param FieldTable $field
* @param UserTable $user
* @param string $output 'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist', 'htmledit'
* @param string $formatting 'tr', 'td', 'div', 'span', 'none', 'table'??
* @param string $reason 'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
* @param int $list_compare_types IF reason == 'search' : 0 : simple 'is' search, 1 : advanced search with modes, 2 : simple 'any' search
* @return mixed
*/
public function getFieldRow( &$field, &$user, $output, $formatting, $reason, $list_compare_types )
{
global $ueConfig;
$results = null;
$oValue = $this->getField( $field, $user, $output, $reason, $list_compare_types );
if ( $reason == 'edit' ) {
$displayMode = $field->get( 'edit', 1 );
} elseif ( $reason == 'register' ) {
$displayMode = $field->get( 'registration', 1 );
} elseif ( $reason == 'search' ) {
$displayMode = 1;
} else {
$displayMode = $field->get( 'profile', 1 );
}
$displayTitle = ( in_array( $displayMode, array( 3, 4 ) ) ? false : true );
if ( $this->isValueEmpty( $oValue )
&& ( $output == 'html' )
&& isset( $ueConfig['showEmptyFields'] ) && ( $ueConfig['showEmptyFields'] == 1 )
&& ( $reason != 'search' )
&& $displayTitle
)
{
$oValue = cbReplaceVars( $ueConfig['emptyFieldsText'], $user, true, true, array( 'reason' => $reason ) );
}
if ( ! $this->isValueEmpty( $oValue ) ) {
if ( cbStartOfStringMatch( $output, 'html' ) ) {
$results = $this->renderFieldHtml( $field, $user, $oValue, $output, $formatting, $reason, array() );
} else {
$results = $oValue;
}
}
return $results;
}
/**
* @param mixed $value
* @return bool
*/
private function isValueEmpty( $value )
{
if ( $value === null ) {
return true;
}
if ( is_string( $value ) ) {
return ( trim( $value ) === '' );
}
if ( is_array( $value ) ) {
return ( count( $value ) === 0 );
}
return false;
}
/**
* Renders a field row with title and description into $output html formating
*
* @param FieldTable $field Using: name, type, title, description, fieldid, profile, displaytitle
* @param UserTable $user User being rendered
* @param string $oValue HTML of the field value to render
* @param string $output 'html', 'htmledit', NOT SUPPORTED IN THIS FUNCTION: 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist'
* @param string $formatting 'tr', 'td', 'div', 'span', 'none', 'table'??
* @param string $reason 'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
* @param string[] $rowClasses CSS classes for the row
* @return string HTML rendering
*/
protected function renderFieldHtml( $field, $user, $oValue, $output, $formatting, $reason, $rowClasses )
{
global $_CB_OneTwoRowsStyleToggle;
$results = null;
$translatedTitle = $this->getFieldTitle( $field, $user, $output, $reason );
if ( $reason == 'edit' ) {
$displayMode = $field->get( 'edit', 1 );
} elseif ( $reason == 'register' ) {
$displayMode = $field->get( 'registration', 1 );
} elseif ( $reason == 'search' ) {
$displayMode = 1;
} else {
$displayMode = $field->get( 'profile', 1 );
}
$twoLines = ( in_array( $displayMode, array( 2, 4 ) ) ? true : false );
$translatedTitle = ( in_array( $displayMode, array( 3, 4 ) ) ? '' : $translatedTitle );
$labelFor = ( ( ( $output == 'htmledit' ) && $field->name ) ? htmlspecialchars( moscomprofilerHTML::htmlId( $field->name . ( preg_match( '/multicheckbox|multiselect|tag/', $field->type ) ? '[]' : null ) ) ) : 'cbfv_' . $field->fieldid );
if ( $field->cssclass ) {
$rowClasses[] = $field->cssclass;
}
if ( preg_match( '/^(?:<(select|input|textarea|button)(?: type="([^"]+)")?|(?:<[^<]+(?:form|input|btn)-(group)[^>]+>))/i', trim( $oValue ), $matches ) ) {
$tag = ( $matches[3] ?? ( $matches[1] ?? '' ) );
$tagType = ( $matches[2] ?? '' );
} else {
$tag = '';
$tagType = '';
}
switch ( $formatting ) {
case 'table':
// ?
break;
case 'tr':
if ( ( $field->name == 'avatar' ) && ( $reason == 'profile' ) ) {
$rowClasses[] = 'cbavatar_tr'; // ugly temporary fix
} else {
$rowClasses[] = 'sectiontableentry' . $_CB_OneTwoRowsStyleToggle;
$_CB_OneTwoRowsStyleToggle = ( $_CB_OneTwoRowsStyleToggle == 1 ? 2 : 1 );
}
$rowClasses[] = 'cb_table_line';
$rowClasses[] = 'cbft_' . $field->type;
if ( $tag ) {
$rowClasses[] = 'cbtt_' . $tag;
}
$results .= '<tr id="cbfr_' . $field->fieldid . '" class="' . implode( ' ', $rowClasses ) . ( $twoLines ? ( trim( $translatedTitle ) === '' ? ' cb_table_line_field' : ' cb_table_line_title' ) : null ) . '">';
if ( ( trim( $translatedTitle ) === '' ) && $twoLines ) {
$results .= '<td id="cbfv_' . $field->fieldid . '" class="fieldCell" colspan="2" style="width: 100%;">'
. $oValue
. '</td>';
} else {
$results .= '<td class="titleCell"' . ( $twoLines ? ' colspan="2"' : null ) . ' style="width: ' . ( $twoLines ? 100 : 25 ) . '%;">'
. ( trim( $translatedTitle ) === '' ? null : '<label for="' . $labelFor . '" id="cblab' . $labelFor . '">' . $translatedTitle . '</label>' )
. '</td>';
if ( $twoLines ) {
$results .= '</tr>'
. '<tr id="cbfrd_' . $field->fieldid . '" class="' . implode( ' ', $rowClasses ) . ' cb_table_line_field">';
}
$results .= '<td id="cbfv_' . $field->fieldid . '" class="fieldCell"' . ( $twoLines ? ' colspan="2"' : null ) . ' style="width: ' . ( $twoLines ? 100 : 75 ) . '%;">'
. $oValue
. '</td>';
}
$results .= '</tr>';
break;
case 'td':
$rowClasses[] = 'fieldCell';
$rowClasses[] = 'cbft_' . $field->type;
if ( $tag ) {
$rowClasses[] = 'cbtt_' . $tag;
}
$results .= '<td id="cbfv_' . $field->fieldid . '" class="' . implode( ' ', $rowClasses ) . '">'
. $oValue
. '</td>';
break;
case 'div':
$rowClasses[] = 'form-group';
$rowClasses[] = 'row';
$rowClasses[] = 'no-gutters';
$rowClasses[] = 'sectiontableentry' . $_CB_OneTwoRowsStyleToggle;
$_CB_OneTwoRowsStyleToggle = ( $_CB_OneTwoRowsStyleToggle == 1 ? 2 : 1 );
$rowClasses[] = 'cbft_' . $field->type;
if ( $tag ) {
$rowClasses[] = 'cbtt_' . $tag;
}
$rowClasses[] = 'cb_form_line';
if ( $twoLines ) {
$rowClasses[] = 'cbtwolinesfield';
}
$results .= '<div class="' . implode( ' ', $rowClasses ) . '" id="cbfr_' . $field->fieldid . '">';
if ( trim( $translatedTitle ) !== '' ) {
$results .= '<label for="' . $labelFor . '" id="cblab' . $labelFor . '" class="col-form-label col-sm-' . ( $twoLines ? 12 : '3 pr-sm-2' ) . '">'
. $translatedTitle
. '</label>';
$colClass = 'col-sm-' . ( $twoLines ? 12 : 9 );
} else {
$colClass = ( $twoLines ? 'col-sm-12' : 'col-sm-9 offset-sm-3' );
}
$results .= '<div class="cb_field ' . $colClass . '">'
. '<div id="cbfv_' . $field->fieldid . '"' . ( ( ( ! $tag ) || ( $tagType === 'range' ) ) && ( ! $twoLines ) ? ' class="form-control-plaintext"' : null ) . '>'
. $oValue
. '</div>'
. '</div>'
. '</div>';
break;
case 'span':
$rowClasses[] = 'cb_field';
$rowClasses[] = 'cbft_' . $field->type;
if ( $tag ) {
$rowClasses[] = 'cbtt_' . $tag;
}
$results .= '<span id="cbfr_' . $field->fieldid . '" class="' . implode( ' ', $rowClasses ) . '">'
. '<span id="cbfv_' . $field->fieldid . '">'
. $oValue
. '</span>'
. '</span>';
break;
case 'ul':
case 'ol':
break;
case 'li':
$rowClasses[] = 'cb_field';
$rowClasses[] = 'cbft_' . $field->type;
if ( $tag ) {
$rowClasses[] = 'cbtt_' . $tag;
}
$results .= '<li id="cbfr_' . $field->fieldid . '" class="' . implode( ' ', $rowClasses ) . '">';
if ( trim( $translatedTitle ) != '' ) {
$results .= '<span class="cb_title">'
. $translatedTitle
. '</span>';
}
$results .= '<span id="cbfv_' . $field->fieldid . '">'
. $oValue
. '</span>'
. '</li>';
break;
case 'none':
$results = $oValue;
break;
default:
$results = '*' . $oValue . '*';
break;
}
return $results;
}
/**
* Accessor:
* Returns a field in specified format
*
* @param FieldTable $field
* @param UserTable $user
* @param string $output 'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist', 'htmledit'
* @param string $reason 'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
* @param int $list_compare_types IF reason == 'search' : 0 : simple 'is' search, 1 : advanced search with modes, 2 : simple 'any' search
* @return mixed
*/
public function getField( &$field, &$user, $output, $reason, $list_compare_types )
{
$valuesArray = array();
foreach ( $field->getTableColumns() as $col ) {
$valuesArray[] = $user->get( $col );
}
$value = implode( ', ', $valuesArray );
switch ( $output ) {
case 'html':
case 'rss':
return $this->formatFieldValueLayout( $this->_formatFieldOutput( $field->name, $value, $output, true ), $reason, $field, $user );
case 'htmledit':
if ( $reason == 'search' ) {
return $this->_fieldSearchModeHtml( $field, $user, $this->_fieldEditToHtml( $field, $user, $reason, 'input', $field->type, $value, '' ), 'text', $list_compare_types );
} else {
return $this->_fieldEditToHtml( $field, $user, $reason, 'input', $field->type, $value, $this->getDataAttributes( $field, $user, $output, $reason ) );
}
default:
return $this->_formatFieldOutput( $field->name, $value, $output, false );
}
}
/**
* Labeller for title:
* Returns a field title
*
* @param FieldTable $field
* @param UserTable $user
* @param string $output 'text' or: 'html', 'htmledit', (later 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist')
* @param string $reason 'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
* @return string
*/
public function getFieldTitle( &$field, &$user, $output, /** @noinspection PhpUnusedParameterInspection */ $reason )
{
if ( $output === 'text' ) {
return strip_tags( cbReplaceVars( $field->title, $user, true, true, array( 'reason' => $reason ) ) );
}
return cbReplaceVars( $field->title, $user, true, true, array( 'reason' => $reason ) );
}
/**
* Labeller for placeholder:
* Returns a field placeholder
*
* @param FieldTable $field
* @param UserTable $user
* @param string $output 'text' or: 'html', 'htmledit', (later 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist')
* @param string $reason 'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
* @return string
*/
public function getFieldPlaceholder( &$field, &$user, $output, /** @noinspection PhpUnusedParameterInspection */ $reason )
{
$placeholder = $field->params->get( 'fieldPlaceholder', null );
if ( ! $placeholder ) {
return null;
}
if ( $output === 'text' ) {
return strip_tags( cbReplaceVars( $placeholder, $user, true, true, array( 'reason' => $reason ) ) );
}
return cbReplaceVars( $placeholder, $user, true, true, array( 'reason' => $reason ) );
}
/**
* Labeller for description:
* Returns a field title
*
* @param FieldTable $field
* @param UserTable $user
* @param string $output 'text' or: 'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist', 'htmledit'
* @param string $reason 'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
* @return string
*/
public function getFieldDescription( &$field, &$user, $output, /** @noinspection PhpUnusedParameterInspection */ $reason )
{
if ( $output === 'text' ) {
return trim( strip_tags( cbReplaceVars( $field->description, $user, true, true, array( 'reason' => $reason ) ) ) );
}
if ( $output === 'htmledit' ) {
return trim( cbReplaceVars( $field->description, $user, true, true, array( 'reason' => $reason ) ) );
}
return null;
}
/**
* Mutator:
* Prepares field data for saving to database (safe transfer from $postdata to $user)
* Override
*
* @param FieldTable $field
* @param UserTable $user RETURNED populated: touch only variables related to saving this field (also when not validating for showing re-edit)
* @param array $postdata Typically $_POST (but not necessarily), filtering required.
* @param string $reason 'edit' for save user edit, 'register' for save registration
*/
public function prepareFieldDataSave( &$field, &$user, &$postdata, $reason )
{
$this->_prepareFieldMetaSave( $field, $user, $postdata, $reason );
foreach ( $field->getTableColumns() as $col ) {
$value = cbGetParam( $postdata, $col );
if ( ( $value !== null ) && ! is_array( $value ) ) {
$value = stripslashes( $value );
if ( $this->validate( $field, $user, $col, $value, $postdata, $reason ) ) {
if ( isset( $user->$col ) && ( (string) $user->$col ) !== (string) $value ) {
$this->_logFieldUpdate( $field, $user, $reason, $user->$col, $value );
}
}
$user->$col = $value;
}
}
}
/**
* Non-Mutator:
* Prepares field data for saving to database (safe transfer from $postdata to $user) when a field does not save e.g. to read-only setting in front-end
* Override
*
* @param FieldTable $field
* @param UserTable $user RETURNED populated: touch only variables related to saving this field (also when not validating for showing re-edit)
* @param array $postdata Typically $_POST (but not necessarily), filtering required.
* @param string $reason 'edit' for save user edit, 'register' for save registration
*/
public function prepareFieldDataNotSaved( &$field, &$user, &$postdata, $reason )
{
}
/**
* Mutator:
* Prepares field data commit
* Override
*
* @param FieldTable $field
* @param UserTable $user RETURNED populated: touch only variables related to saving this field (also when not validating for showing re-edit)
* @param array $postdata Typically $_POST (but not necessarily), filtering required.
* @param string $reason 'edit' for save user edit, 'register' for save registration
*/
public function commitFieldDataSave( &$field, &$user, &$postdata, $reason )
{
}
/**
* Mutator:
* Prepares field data rollback
* Override
*
* @param FieldTable $field
* @param UserTable $user RETURNED populated: touch only variables related to saving this field (also when not validating for showing re-edit)
* @param array $postdata Typically $_POST (but not necessarily), filtering required.
* @param string $reason 'edit' for save user edit, 'register' for save registration
*/
public function rollbackFieldDataSave( &$field, &$user, &$postdata, $reason )
{
}
/**
* Validator:
* Validates $value for $field->required and other rules
* Override
*
* @param FieldTable $field
* @param UserTable $user RETURNED populated: touch only variables related to saving this field (also when not validating for showing re-edit)
* @param string $columnName Column to validate
* @param string $value (RETURNED:) Value to validate, Returned Modified if needed !
* @param array $postdata Typically $_POST (but not necessarily), filtering required.
* @param string $reason 'edit' for save user edit, 'register' for save registration
* @return boolean True if validate, $this->_setErrorMSG if False
*/
public function validate( &$field, &$user, /** @noinspection PhpUnusedParameterInspection */ $columnName, &$value, /** @noinspection PhpUnusedParameterInspection */ &$postdata, $reason )
{
global $_CB_framework, $ueConfig;
if ( ( $_CB_framework->getUi() == 1 ) || ( ( $_CB_framework->getUi() == 2 ) && ( $ueConfig['adminrequiredfields'] == 1 ) ) ) {
// Required field:
if ( ( $field->required == 1 ) && ( $value == '' ) ) {
$this->_setValidationError( $field, $user, $reason, CBTxt::T( 'UE_REQUIRED_ERROR', 'This field is required!' ) );
return false;
}
$isMultiselect = preg_match( '/multicheckbox|multiselect|tag/', $field->type );
$len = ( $isMultiselect ? count( $this->_explodeCBvalues( $value ) ) : cbIsoUtf_strlen( $value ) );
// Minimum field length:
$fieldMinLength = $this->getMinLength( $field );
if ( ( $len > 0 ) && ( $len < $fieldMinLength ) ) {
if ( $isMultiselect ) {
$fieldMinError = CBTxt::T( 'UE_VALIDATE_ERROR_MIN_OPTS_PLEASE', 'Please select a valid [FIELDNAME]: at least ||%%NUMBEROPTSREQUIRED%% option|%%NUMBEROPTSREQUIRED%% options||: you selected ||%%NUMBEROPTSENTERED%% option.|%%NUMBEROPTSENTERED%% options.',
array( '[FIELDNAME]' => $this->getFieldTitle( $field, $user, 'text', $reason ),
'%%NUMBEROPTSREQUIRED%%' => $fieldMinLength,
'%%NUMBEROPTSENTERED%%' => $len ) );
} else {
$fieldMinError = CBTxt::T( 'UE_VALIDATE_ERROR_MIN_CHARS_PLEASE', 'Please enter a valid [FIELDNAME]: at least ||%%NUMBERCHARSREQUIRED%% character|%%NUMBERCHARSREQUIRED%% characters||: you entered ||%%NUMBERCHARSENTERED%% character.|%%NUMBERCHARSENTERED%% characters.',
array( '[FIELDNAME]' => $this->getFieldTitle( $field, $user, 'text', $reason ),
'%%NUMBERCHARSREQUIRED%%' => $fieldMinLength,
'%%NUMBERCHARSENTERED%%' => $len ) );
}
$this->_setValidationError( $field, $user, $reason, $fieldMinError );
return false;
}
// Maximum field length:
$fieldMaxLength = $this->getMaxLength( $field );
if ( $fieldMaxLength && ( $len > $fieldMaxLength ) ) {
if ( $isMultiselect ) {
$fieldMaxError = CBTxt::T( 'UE_VALIDATE_ERROR_MAX_OPTS_PLEASE', 'Please select a valid [FIELDNAME]: maximum ||%%NUMBEROPTSREQUIRED%% option|%%NUMBEROPTSREQUIRED%% options||: you selected ||%%NUMBEROPTSENTERED%% option.|%%NUMBEROPTSENTERED%% options.',
array( '[FIELDNAME]' => $this->getFieldTitle( $field, $user, 'text', $reason ),
'%%NUMBEROPTSREQUIRED%%' => $fieldMaxLength,
'%%NUMBEROPTSENTERED%%' => $len ) );
} else {
$fieldMaxError = CBTxt::T( 'UE_VALIDATE_ERROR_MAX_CHARS_PLEASE', 'Please enter a valid [FIELDNAME]: maximum ||%%NUMBERCHARSREQUIRED%% character|%%NUMBERCHARSREQUIRED%% characters||: you entered ||%%NUMBERCHARSENTERED%% character.|%%NUMBERCHARSENTERED%% characters.',
array( '[FIELDNAME]' => $this->getFieldTitle( $field, $user, 'text', $reason ),
'%%NUMBERCHARSREQUIRED%%' => $fieldMaxLength,
'%%NUMBERCHARSENTERED%%' => $len ) );
}
$this->_setValidationError( $field, $user, $reason, $fieldMaxError );
return false;
}
// Bad words:
if ( ( $reason == 'register' ) && ( in_array( $field->type, array( 'emailaddress', 'primaryemailaddress', 'textarea', 'text', 'webaddress', 'predefined' ) ) ) ) {
$defaultForbidden = 'http:,https:,mailto:,//.[url],<a,</a>,&#';
} else {
$defaultForbidden = '';
}
$forbiddenContent = $field->params->get( 'fieldValidateForbiddenList_' . $reason, $defaultForbidden );
if ( $forbiddenContent != '' ) {
$forbiddenWords = array();
foreach ( explode( ',', $forbiddenContent ) as $forbiddenWord ) {
if ( $forbiddenWord === '' ) {
$forbiddenWords[] = ',';
} else {
$forbiddenWords[] = preg_quote( $forbiddenWord, '/' );
}
}
$replaced = preg_replace( '/' . implode( '|', $forbiddenWords ) . '/i', '', $value );
if ( $replaced != $value ) {
$this->_setValidationError( $field, $user, $reason, CBTxt::T( 'UE_INPUT_VALUE_NOT_ALLOWED', 'This input value is not authorized.' ) );
return false;
}
}
}
return true;
}
/**
* Finder:
* Prepares field data for saving to database (safe transfer from $postdata to $user)
* Override
*
* @param FieldTable $field
* @param UserTable $searchVals RETURNED populated: touch only variables related to saving this field (also when not validating for showing re-edit)
* @param array $postdata Typically $_POST (but not necessarily), filtering required.
* @param int $list_compare_types IF reason == 'search' : 0 : simple 'is' search, 1 : advanced search with modes, 2 : simple 'any' search
* @param string $reason 'edit' for save user edit, 'register' for save registration
* @return cbSqlQueryPart[]
*/
public function bindSearchCriteria( &$field, &$searchVals, &$postdata, $list_compare_types, /** @noinspection PhpUnusedParameterInspection */ $reason )
{
$query = array();
$searchMode = $this->_bindSearchMode( $field, $searchVals, $postdata, 'text', $list_compare_types );
if ( $searchMode ) {
foreach ( $field->getTableColumns() as $col ) {
$value = cbGetParam( $postdata, $col );
if ( ( ( ( $value !== null ) && ( $value !== '' ) ) || ( ( $list_compare_types == 1 ) && in_array( $searchMode, array( 'is', 'isnot' ) ) ) ) && ! is_array( $value ) ) {
$value = stripslashes( $value );
$searchVals->$col = $value;
// $this->validate( $field, $user, $col, $value, $postdata, $reason );
$sql = new cbSqlQueryPart();
$sql->tag = 'column';
$sql->name = $col;
$sql->table = $field->table;
$sql->type = 'sql:field';
$sql->operator = '=';
$sql->value = $value;
$sql->valuetype = 'const:string';
$sql->searchmode = $searchMode;
$query[] = $sql;
}
}
}
return $query;
}
/**
* Returns a field in specified format
*
* @param string $name Sanitized/Safe !!!
* @param string $value
* @param string $output NO 'htmledit' BUT: 'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist'
* @param boolean $htmlspecialchars TRUE: escape for display, FALSE: not escaped will display raw.
* @return mixed
*/
protected function _formatFieldOutput( $name, $value, $output, $htmlspecialchars = true )
{
switch ( $output ) {
case 'html':
case 'rss':
case 'htmledit':
if ( $htmlspecialchars ) {
return htmlspecialchars( ( $value ?? '' ) );
}
return $value;
case 'xml':
if ( $htmlspecialchars ) {
return '<' . htmlspecialchars( ( $name ?? '' ) ) . '>' . htmlspecialchars( htmlspecialchars( ( $value ?? '' ) ) ) . '</' .htmlspecialchars( ( $name ?? '' ) ) . '>';
}
return '<' . htmlspecialchars( ( $name ?? '' ) ) . '>' . htmlspecialchars( ( $value ?? '' ) ) . '</' . htmlspecialchars( ( $name ?? '' ) ) . '>';
case 'json':
return "'" . addslashes( ( $name ?? '' ) ) . "' : '" . addslashes( ( $value ?? '' ) ) . "'";
case 'php':
return array( $name => $value );
case 'fieldslist':
return $name;
/** @noinspection PhpMissingBreakStatementInspection */
case 'csvheader':
$value = $name;
// on purpose fall-through:
case 'csv':
$value = ( $value ?? '' );
if ( ! preg_match( '/",\n\r\t/', $value ) ) {
return $value;
}
return '"' . str_replace( '"', '""', $value ) . '"';
default:
trigger_error( '_formatFieldOutput called with ' . htmlspecialchars( ( $output ?? '' ) ), E_USER_WARNING );
return $value;
}
}
/**
* Returns a field in specified format
*
* @param string $name Sanitized/Safe !!!
* @param string $value Value to format
* @param string $output NO 'htmledit' BUT: 'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist'
* @return mixed
*/
protected function _formatFieldOutputIntBoolFloat( $name, $value, $output )
{
switch ( $output ) {
case 'html':
case 'rss':
return $value;
case 'htmledit':
trigger_error( '_formatFieldOutput called with htmledit', E_USER_WARNING );
return null;
case 'xml':
return '<' . $name . '>' . $value . '</' . $name . '>';
case 'json':
return "'" . $name . "' : " . $value;
case 'php':
return array( $name => $value );
case 'csvheader':
case 'fieldslist':
return $name;
case 'csv':
return $value;
default:
trigger_error( '_formatFieldOutput called with ' . htmlspecialchars( ( $output ?? '' ) ), E_USER_WARNING );
return $value;
}
}
/**
* Reformats a PHP array into $output format
*
* @param FieldTable $field
* @param array $values
* @param string $output 'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist', 'htmledit'
* @param string $listType
* @param string $class
* @param boolean $htmlspecialchars TRUE: escape for display, FALSE: not escaped will display raw.
* @return string|array|null
*/
protected function _arrayToFormat( &$field, $values, $output, $listType = ', ', $class = '', $htmlspecialchars = true )
{
switch ( $output ) {
case 'html':
case 'rss':
if ( $htmlspecialchars ) {
foreach ( $values as $k => $v ) {
$values[$k] = htmlspecialchars( ( $v ?? '' ) );
}
}
switch ( $listType ) {
case 'ul':
case 'ol':
if ( count( $values ) > 0 ) {
if ( $class != '' ) {
$class = ' class="' . htmlspecialchars( $class ) . '"';
}
return '<' . $listType . $class . '><li>' . implode( '</li><li>', $values ) . '</li></' . $listType . '>';
}
return null;
case 'tag':
if ( count( $values ) > 0 ) {
$styles = array( 'badge-primary', 'badge-secondary', 'badge-success', 'badge-danger', 'badge-warning', 'badge-info', 'badge-light', 'badge-dark' );
$defaultStyle = true;
// We don't want to add badge-primary if the classes being added already contains a badge color so lets check if it does:
foreach ( $styles as $style ) {
if ( ! $defaultStyle ) {
break;
}
if ( strpos( $class, $style ) === false ) {
continue;
}
$defaultStyle = false;
}
$class = ' class="badge' . ( $defaultStyle ? ' badge-primary' : null ) . ( $class ? ' ' . htmlspecialchars( $class ) : null ) . '"';
return '<span ' . $class . '>' . implode( '</span> <span ' . $class . '>', $values ) . '</span>';
}
return null;
case ', ':
default:
return implode( $listType, $values );
}
break;
case 'htmledit':
break;
case 'xml':
foreach ( $values as $k => $v ) {
$values[$k] = '<value>' . htmlspecialchars( ( $v ?? '' ) ) . '</value>';
}
return '<' . htmlspecialchars( $field->name ) . '>' . implode( '', $values ) . '</' . htmlspecialchars( $field->name ) . '>';
case 'json':
foreach ( $values as $k => $v ) {
$values[$k] = "'" . addslashes( $v ) . "'";
}
return "'" . addslashes( $field->name ) . "' : { " . implode( ', ', $values ) . " }";
case 'php':
return array( $field->name => $values );
case 'csv':
$valsString = implode( ',', $values );
return $this->_formatFieldOutput( $field->name, $valsString, $output, false );
case 'csvheader':
case 'fieldslist':
default:
break;
}
trigger_error( '_arrayToFormat called with non-implemented output type: ' . htmlspecialchars( ( $output ?? '' ) ), E_USER_WARNING );
return null;
}
/**
* Reformats a PHP array of links into $output format
*
* @param FieldTable $field
* @param array $links
* @param string $output 'html', 'xml', 'json', 'php', 'csvheader', 'csv', 'rss', 'fieldslist', 'htmledit'
* @return string|array|null
*/
protected function _linksArrayToFormat( $field, $links, $output )
{
$values = array();
switch ( $output ) {
case 'xml':
foreach ( $links as $link ) {
if ( isset( $link['url' ] ) ) {
$values[] = '<link>'
. '<url>' . cbSef( $link['url'] ) . '</url>'
. '<title>' . htmlspecialchars( $link['title'] ) . '</title>'
. '<tooltip>' . htmlspecialchars( CBTxt::T( $link['tooltip'] ) ) . '</tooltip>'
. '</link>';
}
}
return '<' . htmlspecialchars( $field->name ) . '>' . implode( '', $values ) . '</' . htmlspecialchars( $field->name ) . '>';
break;
case 'json':
foreach ( $links as $link ) {
if ( isset( $link['url' ] ) ) {
$values[] = array( 'url' => cbSef( $link['url'] ),
'link' => $link['title'],
'tooltip' => CBTxt::T( $link['tooltip'] )
);
}
}
return "'" . addslashes( $field->name ) . "' : " . json_encode( $values, JSON_FORCE_OBJECT );
break;
case 'csv':
foreach ( $links as $link ) {
if ( isset( $link['url' ] ) ) {
$values[] = cbSef( $link['url'] );
}
}
return $this->_formatFieldOutput( $field->name, implode( ',', $values ), $output, false );
break;
default:
foreach ( $links as $link ) {
if ( isset( $link['url' ] ) ) {
$values[] = '<a href="' . cbSef( $link['url'] ) . '" title="' . htmlspecialchars( CBTxt::T( $link['tooltip'] ) ) . '">' . $link['title'] . '</a>';
}
}
return $this->_arrayToFormat( $field, $values, $output, ' ', '', false );
break;
}
}
/**
* @param string $value
* @param string $reason
* @param null|FieldTable $field
* @param null|UserTable $user
* @param boolean $htmlspecialchars
* @param array $extra
* @return string
*/
protected function formatFieldValueLayout( $value, $reason = 'profile', $field = null, $user = null, $htmlspecialchars = true, $extra = array() )
{
if ( in_array( $reason, array( 'profile', 'list', 'search', 'edit', 'register' ) ) && ( $field !== null ) && ( ! $field->get( '_hideLayout', 0 ) ) ) {
switch( $reason ) {
case 'register':
$layout = CBTxt::T( $field->params->get( 'fieldLayoutRegister', '' ) );
break;
case 'edit':
$layout = CBTxt::T( $field->params->get( 'fieldLayoutEdit', '' ) );
break;
case 'list':
$layout = CBTxt::T( $field->params->get( 'fieldLayoutList', '' ) );
break;
case 'search':
$layout = CBTxt::T( $field->params->get( 'fieldLayoutSearch', '' ) );
break;
case 'profile':
default:
$layout = CBTxt::T( $field->params->get( 'fieldLayout', '' ) );
break;
}
// Remove userdata and userfield usage of self from layout to avoid infinite loop:
$layout = trim( preg_replace( '/\[cb:(userdata +field|userfield +field)="' . preg_quote( $field->get( 'name', '' ) ) . '"[^]]+\]/i', '', $layout ) );
if ( $layout ) {
if ( $field->params->get( 'fieldLayoutContentPlugins', 0 ) ) {
$layout = Application::Cms()->prepareHtmlContentPlugins( $layout, 'field.layout', ( $user !== null ? $user->id : 0 ) );
}
if ( $user !== null ) {
$layout = cbReplaceVars( $layout, $user, $htmlspecialchars, true, $extra );
}
$value = str_replace( '[value]', ( $value ?? '' ), $layout );
}
}
return $value;
}
/**
* Private methods for front-end:
*/
/**
* converts to HTML
*
* @param FieldTable $field
* @param UserTable $user
* @param string $reason 'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
* @param string $tag <tag
* @param string $type type="$type"
* @param string $value value="$value"
* @param string $additional 'xxxx="xxx" yy="y"' WARNING: No classes in here, use $classes
* @param array $allValues
* @param boolean $displayFieldIcons
* @param array $classes CSS classes
* @param boolean $translate specify if $allValues should be translated or not
* @return string HTML: <tag type="$type" value="$value" xxxx="xxx" yy="y" />
*/
protected function _fieldEditToHtml( &$field, &$user, $reason, $tag, $type, $value, $additional, $allValues = null, $displayFieldIcons = true, $classes = null, $translate = true )
{
global $_CB_framework, $_PLUGINS;
$readOnly = $this->_isReadOnly( $field, $user, $reason );
$oReq = $this->_isRequired( $field, $user, $reason );
if ( $readOnly ) {
$additional .= ' disabled="disabled"';
$oReq = 0;
}
if ( $oReq ) {
$classes[] = 'required';
}
$inputName = $field->name;
$translatedTitle = $this->getFieldTitle( $field, $user, 'html', $reason );
$translatedPlaceholder = $this->getFieldPlaceholder( $field, $user, 'text', $reason );
$htmlDescription = $this->getFieldDescription( $field, $user, 'htmledit', $reason );
$trimmedDescription = trim( strip_tags( $htmlDescription ) );
$inputDescription = $field->params->get( 'fieldLayoutInputDesc', 1, GetterInterface::INT );
$htmlInput = null;
switch ( $type ) {
case 'radio':
$tooltip = ( $trimmedDescription && $inputDescription ? cbTooltip( $_CB_framework->getUi(), $htmlDescription, $translatedTitle, null, null, null, null, 'data-hascbtooltip="true"' ) : null );
$htmlInput = moscomprofilerHTML::radioListTable( $allValues, $inputName, $additional, 'value', 'text', $value, $field->cols, $field->rows, $field->size, $oReq, $classes, $tooltip, $translate );
break;
case 'radiobuttons':
$tooltip = ( $trimmedDescription && $inputDescription ? cbTooltip( $_CB_framework->getUi(), $htmlDescription, $translatedTitle, null, null, null, null, 'data-hascbtooltip="true"' ) : '' );
$htmlInput = moscomprofilerHTML::radioListButtons( $allValues, $inputName, $tooltip, 'value', 'text', $value, $oReq, $classes, $additional, $translate );
break;
/** @noinspection PhpMissingBreakStatementInspection */
case 'tag':
$classes[] = 'cbSelectTag';
/** @noinspection PhpMissingBreakStatementInspection */
case 'multiselect':
$additional .= ' multiple="multiple"';
$inputName .= '[]';
// no break on purpose for fall-through:
case 'select':
$classes[] = 'form-control';
$additional .= ' class="' . implode( ' ', $classes ) . '"';
if ( $field->size > 0 ) {
$additional .= ' size="' . $field->size . '"';
}
$tooltip = ( $trimmedDescription && $inputDescription ? cbTooltip( $_CB_framework->getUi(), $htmlDescription, $translatedTitle, null, null, null, null, $additional ) : $additional );
$htmlInput = moscomprofilerHTML::selectList( $allValues, $inputName, $tooltip, 'value', 'text', $this->_explodeCBvaluesToObj( $value ), $oReq, true, ( $type == 'tag' ? false : null ), $translate );
break;
case 'multicheckbox':
$tooltip = ( $trimmedDescription && $inputDescription ? cbTooltip( $_CB_framework->getUi(), $htmlDescription, $translatedTitle, null, null, null, null, 'data-hascbtooltip="true"' ) : null );
$htmlInput = moscomprofilerHTML::checkboxListTable( $allValues, $inputName . '[]', $additional, 'value', 'text', $this->_explodeCBvaluesToObj( $value ), $field->cols, $field->rows, $field->size, $oReq, $classes, $tooltip, $translate );
break;
case 'multicheckboxbuttons':
$tooltip = ( $trimmedDescription && $inputDescription ? cbTooltip( $_CB_framework->getUi(), $htmlDescription, $translatedTitle, null, null, null, null, 'data-hascbtooltip="true"' ) : '' );
$htmlInput = moscomprofilerHTML::checkboxListButtons( $allValues, $inputName . '[]', $tooltip, 'value', 'text', $this->_explodeCBvaluesToObj( $value ), $oReq, $classes, $additional, $translate );
break;
case 'checkbox':
$classes[] = 'form-check-input m-0';
if ( $classes ) {
$additional .= ' class="' . implode( ' ', $classes ) . '"';
}
$tooltip = ( $trimmedDescription && $inputDescription ? cbTooltip( $_CB_framework->getUi(), $htmlDescription, $translatedTitle, null, null, null, null, $additional ) : $additional );
$htmlInput = '<div class="cbSingleCntrl m-0 form-check form-check-inline">'
. '<input type="checkbox" id="' . htmlspecialchars( moscomprofilerHTML::htmlId( $inputName ) ) . '" name="' . htmlspecialchars( $inputName ) . '" value="1"' . $tooltip . ' />'
. '</div>';
break;
case 'yesno':
$yes = CBTxt::T( $field->params->getString( 'field_checked_label', '' ) );
if ( $yes === '' ) {
$yes = null; // Explicitly needs NULL for fallback
}
$no = CBTxt::T( $field->params->getString( 'field_unchecked_label', '' ) );
if ( $no === '' ) {
$no = null; // Explicitly needs NULL for fallback
}
if ( $classes ) {
$additional .= ' class="' . implode( ' ', $classes ) . '"';
}
$tooltip = ( $trimmedDescription && $inputDescription ? cbTooltip( $_CB_framework->getUi(), $htmlDescription, $translatedTitle, null, null, null, null, 'data-hascbtooltip="true"' ) : '' );
$htmlInput = moscomprofilerHTML::yesnoButtonList( $inputName, $tooltip, $value, $yes, $no, $additional );
break;
/** @noinspection PhpMissingBreakStatementInspection */
case 'password':
$additional .= ' autocomplete="new-password"';
// on purpose no break here !
case 'text':
case 'primaryemailaddress':
case 'emailaddress':
case 'webaddress':
case 'predefined':
case 'email':
if ( in_array( $type, array( 'email', 'primaryemailaddress' ) ) && ( $reason !== 'search' ) ) {
$type = 'email';
} elseif ( $type != 'password' ) {
$type = 'text'; // Prevent predefined from using invalid html type
}
if ( ( $inputName == 'username' ) && $user->get( 'id', 0, GetterInterface::INT ) ) {
$additional .= ' autocomplete="off"';
}
if ( $field->size > 0 ) {
$additional .= ' size="' . $field->size . '"';
} else {
$additional .= ' size="25"';
}
$fieldMaxLength = $this->getMaxLength( $field );
if ( $fieldMaxLength > 0 ) {
$additional .= ' maxlength="' . $fieldMaxLength . '"';
}
if ( $translatedPlaceholder ) {
$additional .= ' placeholder="' . htmlspecialchars( $translatedPlaceholder ) . '"';
}
$classes[] = 'form-control';
break;
case 'integer':
case 'float':
case 'number':
case 'range':
if ( $type !== 'range' ) {
$type = 'number';
if ( $translatedPlaceholder ) {
$additional .= ' placeholder="' . htmlspecialchars( $translatedPlaceholder ) . '"';
}
$classes[] = 'form-control';
}
$min = $field->params->get( 'integer_minimum', 0, GetterInterface::STRING );
if ( $min != '' ) {
$additional .= ' min="' . ( $type == 'integer' ? (int) $min : (float) $min ) . '"';
}
$max = $field->params->get( 'integer_maximum', 1000000, GetterInterface::STRING );
if ( $max != '' ) {
$additional .= ' max="' . ( $type == 'integer' ? (int) $max : (float) $max ) . '"';
}
$step = $field->params->get( 'integer_step', ( $type == 'float' ? 0.01 : 1 ), ( $type == 'integer' ? GetterInterface::INT : GetterInterface::FLOAT ) );
if ( $step ) {
$additional .= ' step="' . $step . '"';
} else {
$additional .= ' step="any"';
}
break;
case 'datetime':
case 'datetime-local':
$type = 'datetime-local';
if ( $value ) {
// Reformat from SQL to native
$value = Application::Date( (string) $value, 'UTC' )->format( 'Y-m-d\TH:i' );
}
$classes[] = 'form-control';
break;
case 'time':
if ( $value ) {
// Reformat from SQL to native
$value = Application::Date( (string) $value, 'UTC' )->format( 'H:i' );
}
case 'date':
case 'color':
$classes[] = 'form-control';
break;
case 'textarea':
$tag = 'textarea';
$type = null;
if ( $field->cols > 0 ) {
$additional .= ' cols="' . $field->cols . '"';
}
if ( $field->rows > 0 ) {
$additional .= ' rows="' . $field->rows . '"';
}
$fieldMaxLength = $this->getMaxLength( $field );
if ( $fieldMaxLength > 0 ) {
$additional .= ' maxlength="' . $fieldMaxLength . '"';
}
if ( $translatedPlaceholder ) {
$additional .= ' placeholder="' . htmlspecialchars( $translatedPlaceholder ) . '"';
}
$classes[] = 'form-control';
break;
case 'file':
$classes[] = 'form-control';
if ( $field->size > 0 ) {
$additional .= ' size="' . $field->size . '"';
}
break;
case 'html':
return $value;
break;
default:
break;
}
if ( $classes ) {
$additional .= ' class="' . implode( ' ', $classes ) . '"';
}
// if ( $_PLUGINS->triggerListenersExist( 'onInputFieldHtmlRender' ) ) {
// return implode( '', $_PLUGINS->trigger( 'onInputFieldHtmlRender', array( &$this, &$field, &$user, $reason, $tag, $type, $inputName, $value, $additional, $htmlDescription, $allValues, $displayFieldIcons, $oReq ) ) );
// }
if ( $htmlInput === null ) {
$tooltip = ( $trimmedDescription && $inputDescription ? cbTooltip( $_CB_framework->getUi(), $htmlDescription, $translatedTitle, null, null, null, null, $additional ) : $additional );
$htmlInput = '<' . $tag
. ( $type ? ' type="' . htmlspecialchars( $type ) . '"' : '' )
. ' name="' . htmlspecialchars( $inputName ) . '" id="' . htmlspecialchars( moscomprofilerHTML::htmlId( $inputName ) ) . '"'
. ( $tag == 'textarea' ? '' : ' value="' . htmlspecialchars( (string) $value ) . '"' )
. $tooltip
. ( $tag == 'textarea' ? '>' . htmlspecialchars( (string) $value ) . '</textarea>' : ' />' );
if ( ( $type == 'password' ) && $field->params->get( 'passUnmask', true, GetterInterface::BOOLEAN ) ) {
$htmlInput = '<div class="input-group d-inline-flex w-auto cbPasswordUnmask">'
. $htmlInput
. '<div class="input-group-append">'
. '<button type="button" class="btn btn-outline-light border text-body ml-0 rounded-0 cbPasswordUnmaskShow">' . CBTxt::T( 'PASSWORD_UNMASK_SHOW', 'Show' ) . '</button>'
. '<button type="button" class="btn btn-outline-light border text-body ml-0 rounded-0 cbPasswordUnmaskHide hidden">' . CBTxt::T( 'PASSWORD_UNMASK_HIDE', 'Hide' ) . '</button>'
. '</div>'
. '</div>';
}
}
$htmlIcons = $this->_fieldIconsHtml( $field, $user, 'htmledit', $reason, $tag, $type, $value, $additional, $allValues, $displayFieldIcons, $oReq );
$htmlInput = $this->formatFieldValueLayout( $htmlInput, $reason, $field, $user );
if ( $_PLUGINS->triggerListenersExist( 'onInputFieldHtmlRender' ) ) {
return implode( '', $_PLUGINS->trigger( 'onInputFieldHtmlRender', array( $htmlInput, $htmlIcons, $this, $field, $user, $reason, $tag, $type, $inputName, $value, $additional, $htmlDescription, $allValues, $displayFieldIcons, $oReq ) ) );
}
return $htmlInput . $htmlIcons;
}
/**
* Displays field icons
*
* @param FieldTable $field
* @param UserTable $user
* @param string $output
* @param string $reason 'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
* @param string $tag <tag
* @param string $type type="$type"
* @param string $value value="$value"
* @param string $additional 'xxxx="xxx" yy="y"'
* @param array $allValues
* @param boolean $displayFieldIcons
* @param boolean $required
* @return string HTML
*/
protected function _fieldIconsHtml( &$field, &$user, $output, $reason, $tag, $type, $value, $additional, $allValues, $displayFieldIcons, $required )
{
global $_CB_framework, $_PLUGINS;
global $_CB_fieldIconDisplayed; // this is for backwards compatibility with CB 1.2.1 API only, with isset below. New method is to act on $displayFieldIcons referenced parameter in the event.
$return = null;
$results = $_PLUGINS->trigger( 'onFieldIcons', array( &$this, &$field, &$user, $output, $reason, $tag, $type, $value, $additional, $allValues, &$displayFieldIcons, $required ) );
if ( count( $results ) > 0 ) {
$return .= implode( '', $results );
}
if ( $displayFieldIcons && ( $reason != 'search' ) && ! isset( $_CB_fieldIconDisplayed[$field->fieldid] ) ) {
return getFieldIcons( $_CB_framework->getUi(), $required, $field->profile, $this->getFieldDescription( $field, $user, $output, $reason ), $this->getFieldTitle( $field, $user, $output, $reason ), false, $field->params->get( 'fieldLayoutIcons', null ) )
. $return;
}
return $return;
}
/**
* Checks if the field is required or not
*
* @param FieldTable $field
* @param UserTable $user
* @param string $reason
* @return int
*/
protected function _isRequired( $field, /** @noinspection PhpUnusedParameterInspection */ $user, $reason )
{
global $_CB_framework, $ueConfig;
if ( $reason == 'search' ) {
$adminReq = 0;
} else {
$adminReq = $field->required;
if ( ( $_CB_framework->getUi() == 2 )
&& ( $ueConfig['adminrequiredfields']==0 )
&& ! in_array( $field->name, array( 'username', 'email', 'name', 'firstname', 'lastname' ) ) )
{
$adminReq = 0;
}
}
return $adminReq;
}
/**
* Checks if the field is read-only or not
*
* @param FieldTable $field
* @param UserTable $user
* @param string $reason
* @return int
*/
protected function _isReadOnly( $field, /** @noinspection PhpUnusedParameterInspection */ $user, $reason )
{
global $_CB_framework;
$readOnly = $field->readonly;
if ( ( $_CB_framework->getUi() == 2 ) || ( in_array( $reason, array( 'register', 'search' ) ) ) ) {
$readOnly = 0;
}
return $readOnly;
}
/**
* Explodes a CB multi-value into an array of objects with ->value and ->text attributes
*
* @param string $value Values with |*| separations
* @return stdClass[] Values as array
*/
private function _explodeCBvaluesToObj( $value )
{
if ( ! is_array( $value ) ) {
if ( ( $value === '' ) || is_null( $value ) ) {
$value = array();
} else {
$value = explode( '|*|', $value );
}
}
$objArr = array();
foreach( $value as $k => $kv ) {
$objArr[$k] = new stdClass();
$objArr[$k]->value = $kv;
$objArr[$k]->text = $kv;
}
return $objArr;
}
/**
* Explodes a CB multi-value into an array
*
* @param string $value Values with |*| separations
* @return array Values as array
*/
protected function _explodeCBvalues( $value )
{
if ( $value === null || $value === '' ) {
return array();
}
return explode( '|*|', $value );
}
/**
* Implodes an array into a CB multi-value string
*
* @param array $value Values as array
* @return string Values with |*| separations
*/
protected function _implodeCBvalues( $value )
{
return implode( '|*|', $value );
}
/**
* Outputs a Fields-search field for a range
*
* @param FieldTable $field
* @param UserTable $user
* @param string $output
* @param string $reason
* @param string $value
* @param string $minHtml
* @param string $maxHtml
* @param int $list_compare_types IF reason == 'search' : 0 : simple 'is' search, 1 : advanced search with modes, 2 : simple 'any' search
* @param string $class Extra-class (e.g. for jQuery)
* @return string
*/
protected function _fieldSearchRangeModeHtml( &$field, &$user, $output, $reason, $value, $minHtml, $maxHtml, $list_compare_types, $class = '' )
{
$fromHTML = '</span> <span class="cbSearchFromVal">'
. $minHtml
. '</span>'
. '</div>'
. '<div class="mt-2 cbSearchFromToLine">'
. '<span class="cbSearchFromTo cbSearchTo">';
$toHTML = '</span> <span class="cbSearchToVal">'
. $maxHtml
. '</span>';
$html = '<div class="cbSearchFromToLine">'
. '<span class="cbSearchFromTo cbSearchFrom">'
. CBTxt::Th( 'UE_SEARCH_RANGE_BETWEEN_MIN_AND_MAX', 'Between [MINIMUMVALUEINPUTFIELD] and [MAXIMUMVALUEINPUTFIELD]', array( '[MINIMUMVALUEINPUTFIELD]' => $fromHTML, '[MAXIMUMVALUEINPUTFIELD]' => $toHTML ) )
. $this->_fieldIconsHtml( $field, $user, $output, $reason, null, $field->type, $value, 'input', null, true, false )
. '</div>'
;
return $this->_fieldSearchModeHtml( $field, $user, $html, 'isisnot', $list_compare_types, $class );
}
/**
* Notifies plugins to log an update to the field (but to wait for the profile saving events to store that log)
*
* @param FieldTable $field
* @param UserTable $user
* @param string $reason 'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
* @param mixed $oldValues
* @param mixed $newValues
*/
protected function _logFieldUpdate( &$field, &$user, $reason, $oldValues, $newValues )
{
global $_PLUGINS;
$_PLUGINS->trigger( 'onLogChange', array( 'update', 'user', 'field', &$user, &$this->_plugin, &$field, $oldValues, $newValues, $reason ) );
}
/**
* Outputs search format including $html being html with input fields
*
* @param FieldTable $field
* @param UserTable $user
* @param string $html
* @param string $type 'text', 'choice', 'isisnot', 'none'
* @param int $list_compare_types IF reason == 'search' : 0 : simple 'is' search, 1 : advanced search with modes, 2 : simple 'any' search
* @param string $class Extra-class (e.g. for jQuery)
* @return string
*/
protected function _fieldSearchModeHtml( &$field, &$user, $html, $type, $list_compare_types, $class = '' )
{
switch ($list_compare_types ) {
case 1:
// Advanced: all possibilities:
$col = $field->name . '__srmch';
$selected = $user->get( $col );
switch ( $type ) {
case 'text':
$choices = array( 'is' => CBTxt::T( 'UE_MATCH_IS_EXACTLY', 'is exactly' ),
'phrase' => CBTxt::T( 'UE_MATCH_PHRASE', 'contains phrase' ),
'all' => CBTxt::T( 'UE_MATCH_ALL', 'contains all of' ),
'any' => CBTxt::T( 'UE_MATCH_ANY', 'contains any of' ),
'-' => CBTxt::T( 'UE_MATCH_EXCLUSIONS', 'Exclusions:'),
'isnot' => CBTxt::T( 'UE_MATCH_IS_EXACTLY_NOT', 'is exactly not'),
'phrasenot' => CBTxt::T( 'UE_MATCH_PHRASE_NOT', 'doesn\'t contain phrase' ),
'allnot' => CBTxt::T( 'UE_MATCH_ALL_NOT', 'doesn\'t contain all of' ),
'anynot' => CBTxt::T( 'UE_MATCH_ANY_NOT', 'doesn\'t contain any of' )
);
break;
case 'singlechoice':
$choices = array( 'is' => CBTxt::T( 'UE_MATCH_IS', 'is' ),
// 'is' => CBTxt::T( 'UE_MATCH_IS_EXACTLY', 'is exactly' ),
// 'phrase' => CBTxt::T( 'UE_MATCH_PHRASE', 'contains phrase' ),
// 'all' => CBTxt::T( 'UE_MATCH_ALL', 'contains all of' ),
'anyis' => CBTxt::T( 'UE_MATCH_IS_ONE_OF', 'is one of' ),
'-' => CBTxt::T( 'UE_MATCH_EXCLUSIONS', 'Exclusions:'),
'isnot' => CBTxt::T( 'UE_MATCH_IS_NOT', 'is not' ),
// 'phrasenot' => CBTxt::T( 'UE_MATCH_PHRASE_NOT', 'doesn\'t contain phrase' ),
// 'allnot' => CBTxt::T( 'UE_MATCH_ALL_NOT', 'doesn\'t contain all of' ),,
'anyisnot' => CBTxt::T( 'UE_MATCH_IS_NOT_ONE_OF', 'is not one of' )
);
break;
case 'multiplechoice':
$choices = array( 'is' => CBTxt::T( 'UE_MATCH_ARE_EXACTLY', 'are exactly' ),
// 'phrase' => CBTxt::T( 'UE_MATCH_PHRASE', 'contains phrase' ),
'all' => CBTxt::T( 'UE_MATCH_INCLUDE_ALL_OF', 'include all of' ),
'any' => CBTxt::T( 'UE_MATCH_INCLUDE_ANY_OF', 'include any of' ),
'-' => CBTxt::T( 'Exclusions:'),
'isnot' => CBTxt::T( 'UE_MATCH_ARE_EXACTLY_NOT', 'are exactly not' ),
// 'phrasenot' => CBTxt::T( 'UE_MATCH_PHRASE_NOT', 'doesn\'t contain phrase' ),
'allnot' => CBTxt::T( 'UE_MATCH_INCLUDE_ALL_OF_NOT', 'don\'t include all of' ),
'anynot' => CBTxt::T( 'UE_MATCH_INCLUDE_ANY_OF_NOT', 'don\'t include any of' )
);
break;
case 'isisnot':
$choices = array( 'is' => CBTxt::T( 'UE_MATCH_IS', 'is' ),
'-' => CBTxt::T( 'UE_MATCH_EXCLUSIONS_COLUMN', 'Exclusions:'),
'isnot' => CBTxt::T( 'UE_MATCH_IS_NOT', 'is not' )
);
break;
case 'none':
default:
$choices = null;
break;
}
if ( $choices !== null ) {
$drop = array();
$drop[] = moscomprofilerHTML::makeOption( '', CBTxt::T( 'UE_NO_PREFERENCE', 'No preference' ) );
$group = false;
foreach ( $choices as $k => $v ) {
if ( $k == '-' ) {
$drop[] = moscomprofilerHTML::makeOptGroup( $v );
$group = true;
} else {
$drop[] = moscomprofilerHTML::makeOption( $k, $v );
}
}
if ( $group ) {
$drop[] = moscomprofilerHTML::makeOptGroup( null );
}
$additional = ' class="form-control"';
$list = moscomprofilerHTML::selectList( $drop, $field->name . '__srmch', $additional, 'value', 'text', $selected, 1 );
} else {
$list = null;
}
$return = '<div class="cbSearchContainer cbSearchAdvanced' . ( $type ? ' cbSearchAdvanced' . ucfirst( $type ) : '' ) . '">'
. ( $list ? '<div class="cbSearchKind' . ( $type ? ' cbSearchKind' . ucfirst( $type ) : '' ) . '">' . $list . '</div>' : '' )
. '<div class="' . ( $list ? 'mt-2 ' : null ) . 'cbSearchCriteria' . ( $type ? ' cbSearchCriteria' . ucfirst( $type ) : '' ) . ( $class ? ' ' . $class : '' ) . '">' . $html . '</div>'
. '</div>';
break;
case 2: // Simple "contains" and ranges:
case 0:
default:
// Simple: Only 'is' and ranges:
$return = '<div class="cbSearchContainer cbSearchSimple">'
. '<div class="cbSearchCriteria' . ( $class ? ' ' . $class : '' ) . '">' . $html . '</div>'
. '</div>'
;
break;
}
return $return;
}
/**
* Binds search mode
*
* @param FieldTable $field
* @param UserTable $searchVals
* @param array $postdata
* @param string $type 'text', 'choice', 'isisnot', 'none'
* @param int $list_compare_types IF reason == 'search' : 0 : simple 'is' search, 1 : advanced search with modes, 2 : simple 'any' search
* @return array|string|null
*/
protected function _bindSearchMode( $field, &$searchVals, $postdata, $type, $list_compare_types )
{
switch ($list_compare_types) {
case 1:
$fieldNam = $field->name . '__srmch';
$value = cbGetParam( $postdata, $fieldNam );
if ( ( $value !== null ) && ( $value !== '' ) ) {
$searchVals->$fieldNam = stripslashes( $value );
}
break;
case 2:
if ( cbGetParam( $postdata, $field->name ) != null ) {
switch ( $type ) {
case 'text':
case 'multiplechoice':
$value = 'any';
break;
case 'singlechoice':
case 'isisnot':
case 'none':
$value = 'is';
break;
default:
$value = null;
break;
}
} else {
$value = null;
}
break;
case 0:
default:
if ( cbGetParam( $postdata, $field->name ) != null ) {
$value = 'is';
} else {
$value = null;
}
break;
}
return $value;
}
/**
* Binds search range mode
*
* @param FieldTable $field
* @param UserTable $searchVals
* @param array $postdata
* @param string $minName
* @param string $maxName
* @param int $list_compare_types IF reason == 'search' : 0 : simple 'is' search, 1 : advanced search with modes, 2 : simple 'any' search
* @return array|string|null
*/
protected function _bindSearchRangeMode( &$field, &$searchVals, &$postdata, $minName, $maxName, $list_compare_types )
{
switch ($list_compare_types) {
case 1:
$value = $this->_bindSearchMode( $field, $searchVals, $postdata, 'isisnot', $list_compare_types );
break;
case 2:
case 0:
default:
if ( ( cbGetParam( $postdata, $minName ) != null ) || ( cbGetParam( $postdata, $maxName ) != null ) ) {
$value = 'is';
} else {
$value = null;
}
break;
}
return $value;
}
/**
* Prepares field meta-data for saving to database (safe transfer from $postdata to $user)
* Override but call parent
*
* @param FieldTable $field
* @param UserTable $user RETURNED populated: touch only variables related to saving this field (also when not validating for showing re-edit)
* @param array $postdata Typically $_POST (but not necessarily), filtering required.
* @param string $reason 'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
*/
protected function _prepareFieldMetaSave( &$field, &$user, &$postdata, $reason )
{
}
/**
* Adds javascript for a field check by ajax
*
* @deprecated 2.0.0 use cbValidator::getRuleHtmlAttributes instead
*
* @param FieldTable $field
* @param UserTable $user
* @param string $reason
* @param string[]|null $validateParams
* @return null|string Returns string of extra classes (without spaces around)
*/
protected function ajaxCheckField( &$field, &$user, $reason, $validateParams = null )
{
if ( $validateParams !== null ) {
$validateParams[] = cbValidator::getRuleHtmlAttributes( 'cbfield', array( 'user' => (int) $user->id, 'field' => htmlspecialchars( $field->name ), 'reason' => htmlspecialchars( $reason ) ) );
return $this->getDataAttributes( $field, $user, 'htmledit', $reason, $validateParams );
}
return null;
}
/**
* Returns the minimum field length as set
* (public for B/C)
*
* @param FieldTable $field
* @return int
*/
public function getMinLength( $field )
{
return (int) $field->params->get( 'fieldMinLength', 0 );
}
/**
* Returns the maximum field length as set
* (public for B/C)
*
* @param FieldTable $field
* @return int
*/
public function getMaxLength( $field )
{
return (int) $field->maxlength;
}
/**
* formats variable array into data attribute string
*
* @param FieldTable $field
* @param UserTable $user
* @param string $output
* @param string $reason
* @param array $attributeArray
* @return string
*/
protected function getDataAttributes( $field, $user, $output, $reason, $attributeArray = array() )
{
if ( ! is_array( $attributeArray ) ) {
$attributeArray = array();
}
$isMultiselect = preg_match( '/multicheckbox|multiselect|tag/', $field->type );
$fieldMinLength = $this->getMinLength( $field );
if ( $fieldMinLength > 0 ) {
$attributeArray[] = cbValidator::getRuleHtmlAttributes( ( $isMultiselect ? 'minselect' : 'minlength' ), (int) $fieldMinLength );
}
$fieldMaxLength = $this->getMaxLength( $field );
if ( $fieldMaxLength > 0 ) {
$attributeArray[] = cbValidator::getRuleHtmlAttributes( ( $isMultiselect ? 'maxselect' : 'maxlength' ), (int) $fieldMaxLength );
}
if ( isset( $field->_identicalTo ) ) {
$attributeArray[] = cbValidator::getRuleHtmlAttributes( 'equalto', '#' . $field->_identicalTo );
}
if ( count( $attributeArray ) > 0 ) {
$attributes = ' ' . implode( ' ', $attributeArray );
} else {
$attributes = '';
}
return $attributes;
}
/**
* Direct access to field for custom operations, like for Ajax
*
* WARNING: direct unchecked access, except if $user is set, then check well for the $reason ...
*
* @param FieldTable $field
* @param null|UserTable $user
* @param array $postdata
* @param string $reason 'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches (always public!)
* @return string Expected output.
*/
public function fieldClass( /** @noinspection PhpUnusedParameterInspection */ &$field, &$user, &$postdata, $reason )
{
global $_CB_framework;
// simple spoof check security
if ( ! Application::Session()->checkFormToken( 'post', 0 ) ) {
echo '<div class="alert alert-danger">' . CBTxt::Th( 'UE_SESSION_EXPIRED', 'Session expired or cookies are not enabled in your browser. Please press "reload page" in your browser, and enable cookies in your browser.' ) . "</div>";
exit;
}
return false;
}
/**
* Private methods: BACKEND ONLY:
*/
/**
* Loads XML file (backend use only!)
*
* @param FieldTable $field
* @return boolean TRUE if success, FALSE if failed
*/
private function _loadXML( $field )
{
global $_PLUGINS;
if ( ! $field->pluginid ) {
// this field pluginid is not up-to-date, try to find the plugin by the php registration method as last resort: load all user plugins for that:
if ( ! $_PLUGINS->loadPluginGroup( 'user', null, 0 ) ) {
return false;
}
$field->pluginid = $_PLUGINS->getUserFieldPluginId( $field->type );
}
if ( $this->_xml === null ) {
if ( ! $_PLUGINS->loadPluginGroup( null, array( (int) $field->pluginid ), 0 ) ) {
return false;
}
$this->_xml =& $_PLUGINS->loadPluginXML( 'editField', $field->type, $field->pluginid );
if ( $this->_xml === null ) {
return false;
}
}
return true;
}
/**
* Loads field XML (backend use only!)
* TODO: Check if we can make this one private, can't for now as it is used in FieldTable class !
*
* @param FieldTable $field
* @return SimpleXMLElement if success, NULL if failed
*/
public function & _loadFieldXML( $field )
{
if ( $this->_fieldXml === null ) {
if ( $this->_loadXML( $field ) ) {
$fieldTypesXML = $this->_xml->getElementByPath( 'fieldtypes' );
if ( $fieldTypesXML ) {
$this->_fieldXml = $fieldTypesXML->getChildByNameAttr( 'field', 'type', $field->type );
}
}
}
return $this->_fieldXml;
}
/**
* Loads parameters editor (backend use only!)
*
* @param FieldTable $field
* @return cbParamsEditorController|null NULL if not existant
*/
private function & _loadParamsEditor( $field )
{
global $_PLUGINS;
if ( $this->_loadXML( $field ) ) {
$plugin = $_PLUGINS->getPluginObject( $field->pluginid );
$params = new cbParamsEditorController( $field->params, $this->_xml, $this->_xml, $plugin );
$params->setNamespaceRegistry( 'field', $field );
$pluginParams = new Registry( $plugin->params );
$params->setPluginParams( $pluginParams );
} else {
$params = null;
}
return $params;
}
/**
* Methods for CB backend only (do not override):
*/
/**
* Draws parameters editor of the field paramaters (backend use only!)
* TODO: Should be private, but is public because FIeldTable uses it !
*
* @param FieldTable $field
* @param array $options
* @return string HTML if editor available, or NULL
*/
public function drawParamsEditor( FieldTable $field, $options )
{
$params =& $this->_loadParamsEditor( $field );
if ( $params ) {
$params->setOptions( $options );
return $params->draw( 'params', 'fieldtypes', 'field', 'type', $field->type, 'params', true, 'depends', 'div' );
}
return null;
}
/**
* Returns full label of the type of the field (backend use only!)
* TODO: Should be private, but is public because FIeldTable uses it !
*
* @param FieldTable $field
* @param boolean $checkNotSys
* @return boolean TRUE if success, FALSE if failed
*/
public function getFieldTypeLabel( $field, $checkNotSys = true )
{
$fieldXML =& $this->_loadFieldXML( $field );
if ( ! $fieldXML ) {
return null;
}
if ( $checkNotSys && ( $fieldXML->attributes( 'unique' ) == 'true' ) ) {
return null;
}
return $fieldXML->attributes( 'label' );
}
/**
* Returns main table name of $field
* TODO: Should be private, but is public because FIeldTable uses it !
*
* @param FieldTable $field
* @return string
*/
public function getMainTable( $field )
{
$fieldXML =& $this->_loadFieldXML( $field );
if ( $fieldXML ) {
$db = $fieldXML->getElementByPath( 'database' );
if ( $db !== false ) {
$sqlUpgrader = new DatabaseUpgrade();
return $sqlUpgrader->getMainTableName( $db, $field->name, '#__comprofiler' );
}
}
return '#__comprofiler';
}
/**
* Returns array of main table columns names of $field
* TODO: Should be private, but is public because FIeldTable uses it !
*
* @param FieldTable $field
* @return array
*/
public function getMainTableColumns( $field )
{
$fieldXML = $this->_loadFieldXML( $field );
if ( $fieldXML ) {
$db = $fieldXML->getElementByPath( 'database' );
if ( $db !== false ) {
$sqlUpgrader = new DatabaseUpgrade();
$columnsNames = $sqlUpgrader->getMainTableColumnsNames( $db, $field->name );
if ( $columnsNames !== false ) {
return $columnsNames;
}
}
}
return array( $field->name );
}
/**
* Handles SQL XML for the type of the field (backend use only!)
* <database version="1">
* <table name="#__comprofilerUser" class="\CB\Database\Table\UserTable">
* <columns>
* <column name="_rate" nametype="namesuffix" type="sql:decimal(16,8)" unsigned="true" null="true" default="NULL" auto_increment="100" />
*
* TODO: Should be private, but is public because FIeldTable uses it !
*
* @param FieldTable $field Field to adapt
* @param boolean|string $change FALSE: only check, TRUE: change database to match description (deleting non-matching columns if $strictlyColumns == true), 'drop': uninstalls columns/tables
* @param boolean $dryRun FALSE (default): tables are changed, TRUE: Dryrunning
* @param boolean $preferredColumnType Enforce preferred column type
* @return boolean Result
*/
public function adaptSQL( $field, $change = true, $dryRun = false, $preferredColumnType = false )
{
$sqlUpgrader = new DatabaseUpgrade();
$sqlUpgrader->setDryRun( $dryRun );
$old = $sqlUpgrader->setEnforcePreferredColumnType( $preferredColumnType );
$result = $this->checkFixSQL( $sqlUpgrader, $field, $change );
$sqlUpgrader->setEnforcePreferredColumnType( $old );
return $result;
}
/**
* Check or fix field according to XML description if exsitant (or old method otherwise)
*
* @param DatabaseUpgrade $sqlUpgrader
* @param FieldTable $field
* @param boolean $change
* @return boolean
*/
public function checkFixSQL( $sqlUpgrader, $field, $change = true )
{
$fieldXML =& $this->_loadFieldXML( $field );
if ( $fieldXML ) {
$db = $fieldXML->getElementByPath( 'database' );
if ( $db !== false ) {
// <database><table><columns>.... structure:
$success = $sqlUpgrader->checkXmlDatabaseDescription( $db, $field->name, $change );
} else {
$data = $fieldXML->getElementByPath( 'data' );
if ( $data !== false ) {
// <data ....> structure:
$xmlText = '<?xml version="1.0" encoding="UTF-8"?>'
. '<database version="1">'
. '<table name="' . $field->table . '" maintable="true" strict="false" drop="never" shared="true">'
. '<columns>'
. '</columns>'
. '</table>'
. '</database>';
$dbXml = new SimpleXMLElement( $xmlText );
$columns = $dbXml->getElementByPath( 'table/columns' );
$columns->addChildWithAttr( 'column', '', null, $data->attributes() );
$success = $sqlUpgrader->checkXmlDatabaseDescription( $dbXml, $field->name, $change );
} else {
$success = true;
}
}
} else {
// no XML file or no <fieldtype> in xml, must be an old plugin or one which is uninstalled or missing files:
$cols = $field->getTableColumns();
if ( count( $cols ) == 0 ) {
// the comprofiler_files database is upgraded, but this (status) field does not require comprofiler entries:
$success = true;
} else {
// database has been upgraded, take a guess and take first column name as name of the comprofiler table:
// or database has not been upgraded: take name:
$colNamePrefix = $cols[0];
$xmlText = '<?xml version="1.0" encoding="UTF-8"?>'
. '<database version="1">'
. '<table name="#__comprofiler" class="\CB\Database\Table\ComprofilerTable" maintable="true" strict="false" drop="never" shared="true">'
. '<columns>'
. '<column name="" nametype="namesuffix" type="sql:text||sql:varchar(255)" null="true" default="NULL" />'
. '</columns>'
. '</table>'
. '</database>';
$dbXml = new SimpleXMLElement( $xmlText );
$success = $sqlUpgrader->checkXmlDatabaseDescription( $dbXml, $colNamePrefix, $change );
}
}
if ( ! $success ) {
// Temporary way to workaround _error protected, as this whole function should probably go to to new FieldModel:
$field->set( '_error', $sqlUpgrader->getErrors() );
}
/*
var_dump( $success );
echo "<br>\nERRORS: " . $sqlUpgrader->getErrors( "<br /><br />\n\n", "<br />\n" );
echo "<br>\nLOGS: " . $sqlUpgrader->getLogs( "<br /><br />\n\n", "<br />\n" );
//exit;
*/
return $success;
}
/**
* Sets an error message $errorText for $field of $user
*
* @param FieldTable $field
* @param UserTable $user
* @param string $reason 'profile' for user profile view, 'edit' for profile edit, 'register' for registration, 'search' for searches
* @param string $errorText
*/
protected function _setValidationError( &$field, &$user, $reason, $errorText )
{
$this->_setErrorMSG( $this->getFieldTitle( $field, $user, 'text', $reason ) . ' : ' . $errorText );
}
/**
* PRIVATE method: sets the text of the last error
* @access private
*
* @param string $msg error message
* @return boolean true
*/
public function _setErrorMSG( $msg )
{
global $_PLUGINS;
return $_PLUGINS->_setErrorMSG( $msg );
}
}