Project

General

Profile

Bug #3000 » cb.lists.php

krileon, 29 November 2011 15:49

 
<?php
/**
* @version $Id: cb.lists.php 1632 2011-11-02 22:56:25Z beat $
* @package Community Builder
* @subpackage cb.lists.php
* @author Beat and various
* @copyright (C) JoomlaJoe and Beat, www.joomlapolis.com
* @license http://www.gnu.org/licenses/old-licenses/gpl-2.0.html GNU/GPL version 2
*/

// no direct access
if ( ! ( defined( '_VALID_CB' ) || defined( '_JEXEC' ) || defined( '_VALID_MOS' ) ) ) { die( 'Direct Access to this location is not allowed.' ); }

/**
* Users list support class
* Work in progress: do not use outside CB
*/
class cbUsersList {
function drawUsersList( $uid, $listid, $searchFormValuesRAW ) {
global $_CB_database, $_CB_framework, $ueConfig, $_PLUGINS;
$search = null;
$searchGET = cbGetParam( $searchFormValuesRAW, 'search' );
$limitstart = (int) cbGetParam( $searchFormValuesRAW, 'limitstart', 0 );
$searchmode = (int) cbGetParam( $searchFormValuesRAW, 'searchmode', 0 );
$randomParam = (int) cbGetParam( $searchFormValuesRAW, 'rand', 0 );
// old search on formated name:
/* if ( $searchPOST || count( $_POST ) ) {
// simple spoof check security
cbSpoofCheck( 'usersList' );
if ( cbGetParam( $searchFormValuesRAW, "action" ) == "search" ) {
$search = $searchPOST;
}
} else
if ( isset( $searchFormValuesRAW['limitstart'] ) ) {
$search = stripslashes( $searchGET );
}
*/
// get my user and gets the list of user lists he is allowed to see (ACL):
$myCbUser =& CBuser::getInstance( $uid );
if ( $myCbUser === null ) {
$myCbUser =& CBuser::getInstance( null );
}
$myUser =& $myCbUser->getUserData();
/*
$myUser = new moscomprofilerUser( $_CB_database );
if ( $uid ) {
$myUser->load( (int) $uid );
}
*/
$useraccessgroupSQL = " AND useraccessgroupid IN (".implode(',',$_CB_framework->acl->get_groups_below_me( $uid, true )).")";
$_CB_database->setQuery( "SELECT listid, title FROM #__comprofiler_lists WHERE published=1" . $useraccessgroupSQL . " ORDER BY ordering" );
$plists = $_CB_database->loadObjectList();
$lists = array();
$publishedlists = array();
for ( $i=0, $n=count( $plists ); $i < $n; $i++ ) {
$plist =& $plists[$i];
$listTitleNoHtml = strip_tags( cbReplaceVars( getLangDefinition( $plist->title ), $myUser, false, false ) );
$publishedlists[] = moscomprofilerHTML::makeOption( $plist->listid, $listTitleNoHtml );
}
// select either list selected or default list to which he has access (ACL):
if ( $listid == 0 ) {
$_CB_database->setQuery( "SELECT listid FROM #__comprofiler_lists "
. "\n WHERE `default`=1 AND published=1" . $useraccessgroupSQL );
$listid = (int) $_CB_database->loadresult();
if ( $listid == 0 && ( count( $plists ) > 0 ) ) {
$listid = (int) $plists[0]->listid;
}
}
if ( ! ( $listid > 0 ) ) {
echo _UE_NOLISTFOUND;
return;
}
// generates the drop-down list of lists:
if ( count( $plists ) > 1 ) {
$lists['plists'] = moscomprofilerHTML::selectList( $publishedlists, 'listid', 'class="inputbox" size="1" onchange="this.form.submit();"', 'value', 'text', $listid, 1 );
}
// loads the list record:
$row = new moscomprofilerLists( $_CB_database );
if ( ( ! $row->load( (int) $listid ) ) || ( $row->published != 1 ) ) {
echo _UE_LIST_DOES_NOT_EXIST;
return;
}
if ( ! allowAccess( $row->useraccessgroupid,'RECURSE', $_CB_framework->acl->get_groups_below_me( $uid, true ) ) ) {
echo _UE_NOT_AUTHORIZED;
return;
}
$params = new cbParamsBase( $row->params );
$hotlink_protection = $params->get( 'hotlink_protection', 0 );
if ( $hotlink_protection == 1 ) {
if ( ( $searchGET !== null ) || $limitstart ) {
cbSpoofCheck( 'usersList', 'GET' );
}
}
$limit = (int) $params->get( 'list_limit' );
if ( $limit == 0 ) {
$limit = (int) $ueConfig['num_per_page'];
}
$showPaging = $params->get( 'list_paging', 1 );
if ( $showPaging != 1 ) {
$limitstart = 0;
}
$isModerator = isModerator( $_CB_framework->myId() );
$_PLUGINS->loadPluginGroup( 'user' );
// $plugSearchFieldsArray = $_PLUGINS->trigger( 'onStartUsersList', array( &$listid, &$row, &$search, &$limitstart, &$limit ) );
$_PLUGINS->trigger( 'onStartUsersList', array( &$listid, &$row, &$search, &$limitstart, &$limit ) );
// handles the users allowed to be listed in the list by ACL:
$allusergids = array();
$usergids = explode( ',', $row->usergroupids );
/* This was a bug tending to list admins when "public backend" was checked, and all frontend users when "public backend was checked. Now just ignore them:
foreach( $usergids AS $usergid ) {
$allusergids[] = $usergid;
if ($usergid==29 || $usergid==30) {
$groupchildren = array();
$groupchildren = $_CB_framework->acl->get_group_children( $usergid, 'ARO','RECURSE' );
$allusergids = array_merge($allusergids,$groupchildren);
}
}
*/
$allusergids = array_diff( $usergids, $_CB_framework->acl->mapGroupNamesToValues( array( 'Public', 'Backend' ) ) );
$usergids = implode( ",", $allusergids );
// build SQL Select query:
$random = 0;
if( $row->sortfields != '' ) {
$matches = null;
if ( preg_match( '/^RAND\(\)\s(ASC|DESC)$/', $row->sortfields, $matches ) ) {
// random sorting needs to have same seed on pages > 1 to not have probability to show same users:
if ( $limitstart ) {
$random = (int) $randomParam;
}
if ( ! $random ) {
$random = rand( 0, 32767 );
}
$row->sortfields = 'RAND(' . (int) $random . ') ' . $matches[1];
}
$orderby = "\n ORDER BY " . $row->sortfields;
}
$filterby = '';
if ( $row->filterfields != '' ) {
$filterRules = utf8RawUrlDecode( substr( $row->filterfields, 1 ) );
if ( $_CB_framework->myId() ) {
$user = new moscomprofilerUser( $_CB_database );
if ( $user->load( (int) $_CB_framework->myId() ) ) {
$filterRules = cbReplaceVars( $filterRules, $user, array( $_CB_database, 'getEscaped' ), false, array() );
}
}
$filterby = " AND ". $filterRules;
}
// Prepare part after SELECT .... " and before "FROM" :
$tableReferences = array( '#__comprofiler' => 'ue', '#__users' => 'u' );
// Fetch all fields:
$tabs = $myCbUser->_getCbTabs(); // new cbTabs( 0, 1 ); //TBD: later: this private method should not be called here, but the whole users-list should go into there and be called here.
$allFields = $tabs->_getTabFieldsDb( null, $myUser, 'list' );
// $_CB_database->setQuery( "SELECT * FROM #__comprofiler_fields WHERE published = 1" );
// $allFields = $_CB_database->loadObjectList( 'fieldid', 'moscomprofilerFields', array( &$_CB_database ) );
//Make columns array. This array will later be constructed from the tabs table:
$columns = array();
for ( $i = 1; $i < 50; ++$i ) {
$enabledVar = "col".$i."enabled";
if ( ! isset( $row->$enabledVar ) ) {
break;
}
$titleVar = "col".$i."title";
$fieldsVar = "col".$i."fields";
$captionsVar = "col".$i."captions";
if ( $row->$enabledVar == 1 ) {
$col = new stdClass();
$col->fields = ( $row->$fieldsVar ? explode( '|*|', $row->$fieldsVar ) : array() );
$col->title = $row->$titleVar;
$col->titleRendered = $myCbUser->replaceUserVars( $col->title );
$col->captions = $row->$captionsVar;
// $col->sort = 1; //All columns can be sorted
$columns[$i] = $col;
}
}
// build fields and tables accesses, also check for searchable fields:
$searchableFields = array();
$fieldsSQL = cbUsersList::getFieldsSQL( $columns, $allFields, $tableReferences, $searchableFields, $params );
$_PLUGINS->trigger( 'onAfterUsersListFieldsSql', array( &$columns, &$allFields, &$tableReferences ) );
$tablesSQL = array();
$joinsSQL = array();
$tablesWhereSQL = array( 'block' => 'u.block = 0',
'approved' => 'ue.approved = 1',
'confirmed' => 'ue.confirmed = 1'
);
if ( checkJversion() == 2 ) {
$joinsSQL[] = 'JOIN #__user_usergroup_map g ON g.`user_id` = u.`id`';
}
if ( ! $isModerator ) {
$tablesWhereSQL['banned'] = 'ue.banned = 0';
}
if ( $usergids ) {
if ( checkJversion() == 2 ) {
$tablesWhereSQL['gid'] = 'g.group_id IN (' . $usergids . ')';
} else {
$tablesWhereSQL['gid'] = 'u.gid IN (' . $usergids . ')';
}
}
foreach ( $tableReferences as $table => $name ) {
if ( $name == 'u' ) {
$tablesSQL[] = $table . ' ' . $name;
} else {
$joinsSQL[] = 'JOIN ' . $table . ' ' . $name . ' ON ' . $name . '.`id` = u.`id`';
}
}
// handles search criterias:
$list_compare_types = $params->get( 'list_compare_types', 0 );
$searchVals = new stdClass();
$searchesFromFields = $tabs->applySearchableContents( $searchableFields, $searchVals, $searchFormValuesRAW, $list_compare_types );
$whereFields = $searchesFromFields->reduceSqlFormula( $tableReferences, $joinsSQL, TRUE );
if ( $whereFields ) {
$tablesWhereSQL[] = '(' . $whereFields . ')';
/*
if ( $search === null ) {
$search = '';
}
*/
}
$_PLUGINS->trigger( 'onBeforeUsersListBuildQuery', array( &$tablesSQL, &$joinsSQL, &$tablesWhereSQL ) );
$queryFrom = "FROM " . implode( ', ', $tablesSQL )
. ( count( $joinsSQL ) ? "\n " . implode( "\n ", $joinsSQL ) : '' )
. "\n WHERE " . implode( "\n AND ", $tablesWhereSQL );
// handles old formatted names search:
/*
if ( $search != '' ) {
$searchSQL = cbEscapeSQLsearch( strtolower( $_CB_database->getEscaped( $search ) ) );
$queryFrom .= " AND (";
$searchFields = array();
if ( $ueConfig['name_format']!='3' ) {
$searchFields[] = "u.name LIKE '%%s%'";
}
if ( $ueConfig['name_format']!='1' ) {
$searchFields[] = "u.username LIKE '%%s%'";
}
if ( is_array( $plugSearchFieldsArray ) ) {
foreach ( $plugSearchFieldsArray as $v ) {
if ( is_array( $v ) ) {
$searchFields = array_merge( $searchFields, $v );
}
}
}
$queryFrom .= str_replace( '%s', $searchSQL, implode( " OR ", $searchFields ) );
$queryFrom .= ")";
}
*/
$queryFrom .= " " . $filterby;
$_PLUGINS->trigger( 'onBeforeUsersListQuery', array( &$queryFrom, 1, $listid ) ); // $uid = 1
$errorMsg = null;
// counts number of users and loads the listed fields of the users if not in search-form-only mode:
if ( $searchmode == 0 ) {
if ( checkJversion() == 2 ) {
$_CB_database->setQuery( "SELECT COUNT(DISTINCT u.id) " . $queryFrom );
} else {
$_CB_database->setQuery( "SELECT COUNT(*) " . $queryFrom );
}
$total = $_CB_database->loadResult();
if ( ( $limit > $total ) || ( $limitstart >= $total ) ) {
$limitstart = 0;
}
// $query = "SELECT u.id, ue.banned, '' AS 'NA' " . ( $fieldsSQL ? ", " . $fieldsSQL . " " : '' ) . $queryFrom . " " . $orderby
if ( checkJversion() == 2 ) {
$query = "SELECT DISTINCT ue.*, u.*, '' AS 'NA' " . ( $fieldsSQL ? ", " . $fieldsSQL . " " : '' ) . $queryFrom . " " . $orderby;
} else {
$query = "SELECT ue.*, u.*, '' AS 'NA' " . ( $fieldsSQL ? ", " . $fieldsSQL . " " : '' ) . $queryFrom . " " . $orderby;
}
$_CB_database->setQuery( $query, (int) $limitstart, (int) $limit );
$users = $_CB_database->loadObjectList( null, 'moscomprofilerUser', array( &$_CB_database ) );
foreach ( $users as $k => $v ) {
$users[$k]->afterBindFromDatabase(); // load gids and fix CMS database storage bugs
}
if ( ! $_CB_database->getErrorNum() ) {
// creates the CBUsers in cache corresponding to the $users:
foreach ( array_keys( $users ) as $k) {
CBuser::setUserGetCBUserInstance( $users[$k] );
}
} else {
$users = array();
$errorMsg = _UE_ERROR_IN_QUERY_TURN_SITE_DEBUG_ON_TO_VIEW;
}
if ( count( get_object_vars( $searchVals ) ) > 0 ) {
$search = '';
} else {
$search = null;
}
} else {
$total = null;
$users = array();
if ( $search === null ) {
$search = '';
}
}
// Compute itemId of users in users-list:
$Itemid = $_CB_framework->itemid();
if ( $Itemid ) {
$option_itemid = (int) $Itemid;
} else {
$option_itemid = getCBprofileItemid( 0 );
}
HTML_comprofiler::usersList( $row, $users, $columns, $allFields, $lists, $listid, $search, $searchmode, $option_itemid, $limitstart, $limit, $total, $myUser, $searchableFields, $searchVals, $tabs, $list_compare_types, $showPaging, $hotlink_protection, $errorMsg, $random );
}
/**
* Creates the column references for the userlist query
* @static
*
* @param array $columns
* @param array $allFields
* @param array $tables
* @param array $searchableFields
* @param cbParamsBase $params
* @return string
*/
function getFieldsSQL( &$columns, &$allFields, &$tables, &$searchableFields, &$params ){
$colRefs = array();
$newtableindex = 0;
$list_search = (int) $params->get( 'list_search', 1 );
foreach ( $columns as $i => $column ) {
foreach ( $column->fields as $k => $fieldid ) {
if ( isset( $allFields[$fieldid] ) ) {
// now done in field fetching:
// if ( ! is_object( $allFields[$fieldid]->params ) ) {
// $allFields[$fieldid]->params = new cbParamsBase( $allFields[$fieldid]->params );
// }
$field = $allFields[$fieldid];
if ( ! array_key_exists( $field->table, $tables ) ) {
$newtableindex++;
$tables[$field->table] = 't'.$newtableindex;
}
/*
if ( $field->name == 'avatar' ) {
$colRefs['avatarapproved'] = 'ue.`avatarapproved`';
$colRefs['name'] = 'u.`name`';
$colRefs['username'] = 'u.`username`';
}
if ( $field->type == 'formatname' ) {
$colRefs['name'] = 'u.`name`';
$colRefs['username'] = 'u.`username`';
}
*/
if ( ( $tables[$field->table][0] != 'u' ) && ( $field->name != 'NA' ) ) { // CB 1.1 table compatibility : TBD: remove after CB 1.2
foreach ( $field->getTableColumns() as $col ) {
$colRefs[$col] = $tables[$field->table] . '.' . $field->_db->NameQuote( $col );
}
}
if ( $field->searchable && ( $list_search == 1 ) ) {
$searchableFields[] =& $allFields[$fieldid];
}
$allFields[$fieldid]->_listed = true;
} else {
// field unpublished or deleted but still in list: remove field from columns, so that we don't handle it:
unset( $columns[$i]->fields[$k] );
}
}
}
if ( $list_search == 2 ) {
foreach ( $allFields as $fieldid => $field ) {
if ( $field->searchable ) {
$searchableFields[] =& $allFields[$fieldid];
}
}
}
return implode( ', ', $colRefs );
}
/**
* Outputs javascript for the advanced search feature on users lists
* @static
*
* @param $search null: show just search button, 'onlyactive': show also activated searches
*/
function outputAdvancedSearchJs( $search ) {
global $_CB_framework;

// Searchable fields appearing in the users list:
// Search box:
//TBD: display if there is a search criteria:
if ( $search === null || $search == 'onlyactive' ) {
// Show the "Search" button:
$jsSearch = " $('#cbUserListsSearchTrigger').show();";
if ( $search === null ) {
// Hide the Search Criteria part and Results title:
$jsSearch .= "\n $('.cbUserListSearch').hide();";
} else {
// Show Criterias, but hide inactive fields:
$jsSearch .= "\n var allSearchLines = $('#cbUserListsSearcher .cbUserListSearchFields .cb_form_line');"
. "\n var inactiveSearchLines = allSearchLines.filter( function() {"
. "\n var searchKindSelector = $(this).find('.cbSearchKind select');"
. "\n if (searchKindSelector.length > 0) {"
. "\n return searchKindSelector.val() == '';"
. "\n } else {"
. "\n var searchFields = $(this).find('.cbSearchCriteria select,.cbSearchCriteria input,.cbSearchCriteria textarea');"
. "\n return ((searchFields.length > 0) && (searchFields.filter( function() { return $(this).val() != ''; }).length == 0));"
. "\n }"
. "\n });"
. "\n inactiveSearchLines.hide();"
. "\n if ( inactiveSearchLines.size() < allSearchLines.size() ) {"
. "\n $('.cbUserListSearch').show();"
. "\n }"
;
}
// When button <a> link is clicked:
$jsSearch .= "\n $('#cbUserListsSearchTrigger').click( function() {"
// Show the lines hidden in case of onlyactive:
. "\n $('#cbUserListsSearcher .cbUserListSearchFields .cb_form_line').show();"
// Hide the button:
. "\n $('#cbUserListsSearchTrigger').hide('medium', function() {"
// Show the Search Criteria part:
. "\n $('#cbUserListsSearcher').slideDown('slow');"
. "\n } );"
// And avoid the <a> link being followed:
. "\n $('div.cbSearchKind select').each(function() {if ($(this).val() == '') $(this).parent( 'div' ).next('div.cbSearchCriteria').hide();});"
. "\n return false;"
. "\n } );"
;
} else {
/*
$ajaxCode = "$('#cbUserListsSearchTrigger').hide();"
. "$('.cbUserListSearch').show();"
. "} );"
;
$_CB_framework->outputCbJQuery( $ajaxCode );
*/
// hide unneeded fields:
$jsSearch = "\n $('div.cbSearchKind select').each(function() {if ($(this).val() == '') $(this).parent( 'div' ).next('div.cbSearchCriteria').hide();});"
. "\n $('.cbUserListSearch').show();";
;
}
$_CB_framework->outputCbJQuery( $jsSearch );

// When a search kind ('is', 'is not', 'contains', etc) is clicked (change does not work correctly in some safari 2 and IE 6 versions):
$searchTabJs = "\n{"
. "\n function cbsearchkrit(thisSelect) {"
// Get value of the selected option:
. "\n var kindval = $(thisSelect).val();"
. "\n if ( kindval == '' ) {"
// Hide the search criteria if there is 'no preference' selected:
. "\n $(thisSelect).parent( 'div' ).next('div.cbSearchCriteria').slideUp('slow');"
. "\n } else {"
// Otherwise show the search criteria:
. "\n $(thisSelect).parent( 'div' ).next('div.cbSearchCriteria').slideDown('slow');"
// Check for search kind being precise search:
. "\n if ( ( kindval == 'is' ) || ( kindval == 'isnot' ) ) {"
// For radio buttons, insure they are (again) radios: unfortunately, DOM doesn't allow to change type of input on the fly, so do it by regex replacing html:
. "\n $(thisSelect).parent('div').next('div.cbSearchCriteria.cb__js_radio').find('input:checkbox').parent().each( function() {"
. "\n return $(this).html( $(this).html().replace(/(name=)(\"?)([^\"\\[ >]+)(\\[\\])(\"?)([ >])/g, '\$1\"\$3\"\$6').replace(/type=\"?checkbox\"?/g,'type=\"radio\"') );"
. "\n } );"
// For single-selects, insure they are not multiple anymore:
. "\n $(thisSelect).parent('div').next('div.cbSearchCriteria.cb__js_select').each( function() {"
. "\n return $(this).html( $(this).html().replace(/(name=)(\"?)([^\"\\[ >]+)(\\[\\])(\"?)([ >])/g, '\$1\"\$3\"\$6').replace(/multiple(=(\"?)multiple(\"?))?/gi,'') );"
. "\n } );"
. "\n } else {"
// If search criteria is multiple, then make also radios into checkboxes (and below single-selects into multi-selects):
. "\n $(thisSelect).parent('div').next('div.cbSearchCriteria.cb__js_radio').find('input:radio').parent().each( function() {"
. "\n return $(this).html( $(this).html().replace(/(name=)(\"?)([^\"\\[ >]+)(\\[\\])?(\"?)([ >])/g, '\$1\"\$3\\[\\]\"\$6').replace(/type=\"?radio\"?/g,'type=\"checkbox\"') );"
. "\n } );"
. "\n $(thisSelect).parent('div').next('div.cbSearchCriteria.cb__js_select').each( function() {"
. "\n return $(this).html( $(this).html().replace(/(name=)(\"?)([^\"\\[ >]+)(\\[\\])?(\"?)([ >])/g, '\$1\"\$3\\[\\]\"\$6').replace(/(<select )/gi,'\$1multiple=\"multiple\" ').replace(/size=(\"?)[^\" >]*(\"?)/g,'size=\"0\"') );"
. "\n } );"
. "\n }"
. "\n }"
. "\n }"
. "\n $('div.cbSearchKind select').click( function() {"
. "\n cbsearchkrit( this );"
// At page startup fires the click event, which executes the callback just defined above:
. "\n } ).each( function() { cbsearchkrit(this); });" //.click();"
. "\n $('div.cbSearchKind select').change( function() {"
. "\n cbsearchkrit( this );"
// At search startup the fields are hidden as just defined above
. "\n $('div.cbSearchKind select').each(function() { cbsearchkrit(this); });"
. "\n } );"
. "\n}"
;
$_CB_framework->outputCbJQuery( $searchTabJs );
}
}
?>
(2-2/2)