<?php
/**
* This file implements the ResultSel class.
*
* This file is part of the evoCore framework - {@link http://evocore.net/}
* See also {@link https://github.com/b2evolution/b2evolution}.
*
* @license GNU GPL v2 - {@link http://b2evolution.net/about/gnu-gpl-license}
*
* @copyright (c)2003-2020 by Francois Planque - {@link http://fplanque.com/}
* Parts of this file are copyright (c)2005-2006 by PROGIDISTRI - {@link http://progidistri.com/}.
*
*
* @package evocore
*/
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );
load_class('_core/ui/results/_results.class.php', 'Results' );
/**
* ResultSel class: displays Results and provides Selection capabilities
*
*/
class ResultSel extends Results
{
/**
* var Form
*/
var $Form;
var $current_selection_ID;
var $table_selections;
var $field_selected;
var $field_selection;
/**
* Constructor
*
* @param string fieldname of item ID to select on
* @param string
* @param string
* @param string
* @param string
* @param string
* @param string
* @param integer current selection ID
* @param string SQL query
* @param NULL|string SQL query used to count the total # of rows (if NULL, we'll try to COUNT(*) by ourselves)
* @param string prefix to differentiate page/order params when multiple Results appear one same page
* @param string default ordering of columns (special syntax) if not URL specified
* @param integer number of lines displayed on one screen
*/
function __construct( $field_ID, $table_selections, $field_sel_ID, $field_sel_name,
$table_objsel, $field_selected, $field_selection, $current_selection_ID,
$sql, $count_sql = NULL, $param_prefix = '', $default_order = '', $limit = 20 )
{
// Call parent:
parent::__construct( $sql, $param_prefix, $default_order, $limit, $count_sql );
if( ! check_user_perm( 'selections', 'view' ) )
{ // User is NOT allowed to view selections
// Don't do any more then base class:
return;
}
$this->current_selection_ID = $current_selection_ID;
$this->table_selections = $table_selections;
$this->field_sel_ID = $field_sel_ID;
$this->field_sel_name = $field_sel_name;
$this->table_objsel = $table_objsel;
$this->field_selected = $field_selected;
$this->field_selection = $field_selection;
// Presets a selection checkbox:
$this->cols[] = array(
'th' => /* TRANS: abbr. for "Selection" */ T_('Sel'),
'td_class' => 'shrinkwrap',
'td' => '%selection_checkbox( #'.$field_ID.'#, \''.$this->param_prefix.'\' )%',
);
}
/**
* Display list/table start preceeded by <form> opening.
*/
function display_list_start()
{
global $item_ID_array;
if( ! check_user_perm( 'selections', 'view' ) )
{ // User is NOT allowed to view selections
// Don't do any more then base class:
parent::display_list_start();
return;
}
$this->Form = new Form( regenerate_url('', '', '', '&'), $this->param_prefix.'selections_checkchanges', 'post', 'none' ); // COPY!!
$this->Form->begin_form( '' );
if( $this->total_pages > 0 )
{ // We have rows to display, we want the selection stuff:
// Need it to check in the next page if the selection has to be updated
$this->Form->hidden( $this->param_prefix.'previous_sel_ID', $this->current_selection_ID );
// Sets the cols_check global variable to verify if checkboxes
// have to be checked in the result set :
cols_check( $this->current_selection_ID, $this->table_objsel, $this->field_selected, $this->field_selection );
// item_ID_array must be emptied to avoid conflicts with previous result sets :
// TODO: put this into object
$item_ID_array = array();
}
// list/table start:
parent::display_list_start();
}
/**
* Display list/table end followed by </form> closing.
*
* Typically outputs </ul> or </table>
*/
function display_list_end()
{
if( ! check_user_perm( 'selections', 'view' ) )
{ // User is NOT allowed to view selections
// Don't do any more then base class:
parent::display_list_end();
return;
}
// list/table end:
parent::display_list_end();
$this->Form->end_form();
}
/**
* Display functions
*/
function display_functions()
{
$this->functions_area = array( 'callback' => array( 'this', 'selection_menu' ) );
parent::display_functions();
}
/**
* Callback for selection menu
*/
function selection_menu()
{
global $item_ID_array;
$can_edit = check_user_perm( 'selections', 'edit' );
if( $can_edit )
{ // links to check all and uncheck all
echo $this->Form->checkbox_controls( '$all$', array( 'button_class' => 'btn btn-default' ) );
}
if( check_user_perm( 'selections', 'view' ) )
{
// construction of the select menu :
$selection_name = selection_select_tag( $this->param_prefix, $this->table_selections, $this->field_sel_name, $this->field_sel_ID, $this->current_selection_ID );
}
if( $can_edit )
{
$this->Form->text( 'selection_'.$this->param_prefix.'name', $selection_name, 25, T_('Selection name'), '', 60 );
// List of IDs displayed on this page (needed for deletes):
$this->Form->hidden( 'item_ID_list', implode( ',', $item_ID_array ) );
// actionArray[update_selection] is experimental
$this->Form->submit( array( 'actionArray[update_'.$this->param_prefix.'selection]', T_('Update selection'), 'SaveButton' ) );
}
}
}
/**
* Sets the cols_check global variable to verify if checkboxes have to be checked in the result set
*
* @param the selection ID
* @param the name of the attachment table (which links the items and the selections
* @param the item id field
* @param the selection id field
*/
function cols_check( $selection_ID, $sel_table, $sel_table_item, $sel_table_selection )
{
global $DB, $cols_check;
if( $selection_ID !== 0 )
{
$sql_check = 'SELECT '.$sel_table_item.' FROM '.$sel_table.' WHERE '.$sel_table_selection.'='.$selection_ID;
$cols_check = $DB->get_col( $sql_check );
}
else
{
$cols_check = array();
}
}
/**
* Display a checkbox allowing to add the item to a selection
*
* Only one checkbox will be displayed for each ID.
* IDs which are already in the selection will be pre-checked.
*
* @deprecated should go into ResultSel class
*
* @param integer item ID
* @param string item name / prefix for form values
* @return string the correct input tag
*/
function selection_checkbox( $item_ID, $param_prefix )
{
// List of checkboxes to pre-check:
global $cols_check;
// List of already displayed checkboxes (can be used outside to get a list of checkboxes which have been displayed)
global $item_ID_array;
if( in_array( $item_ID, $item_ID_array ) )
{ // We have already displayed a checkbox for this ID
return ' '; // nbsp is for IE...
}
$item_ID_array[] = $item_ID; //construction of the ID list
$r = '';
if( check_user_perm( 'selections', 'edit' ) )
{ // User is allowed to edit
$r .= '<input type="checkbox" class="checkbox" name="'.$param_prefix.'items[]" value="'.$item_ID.'"';
if( in_array( $item_ID, $cols_check ) )
{ // already in selection:
$r .= ' checked="checked" ';
}
$r .= ' />';
}
else
{ // User CANNOT edit:
if( in_array( $item_ID, $cols_check ) )
{ // already in selection:
$r .= '*';
}
else
{
$r .= ' ';
}
}
return $r;
}
/**
* Creates the select tag in the search menu and fills it with the appropriate option tags
*
* @param string the selection category prefix(the one used during the construction of the result object)
* @param string the name of the table containing the selections
* @param string the name field in the selection table
* @param string the id field in the selection table
* @param integer the current selection id
*/
function selection_select_tag(
$category_prefix,
$selections_table,
$selections_table_name,
$selections_table_ID,
$selection_ID
)
{
global $DB, $selection_name;
$r = T_('Selection');
$r .= ' <select name="selection_'.$category_prefix.'ID"
onchange="selform = get_form( this );
selform.elements[\''.$category_prefix.'previous_sel_ID\'].value=-1;
selform.submit()" >'."\n";
// in the onchange attribute, option_db is set to -1 to avoid updating the database
if( check_user_perm( 'selections', 'edit' ) )
{ // User is allowed to edit
$r .= '<option value="0">'.T_('New selection')."</option>\n";
}
else
{ // User CANNOT edit:
$r .= '<option value="0">'.T_('None')."</option>\n";
}
$sql = 'SELECT * FROM '.$selections_table.' ORDER BY '.$selections_table_name;
$rows = $DB->get_results( $sql );
if( !empty( $rows ) )
{
$selection_name = '';
foreach( $rows as $row )
{ // construction of the option tags
if( $row->$selections_table_ID == $selection_ID )
{ // option selected by default
$selected = ' selected="selected" ';
$selection_name = $row->$selections_table_name;
}
else
{
$selected = '';
}
$r .= '<option value="'.$row->$selections_table_ID.'" '.$selected.' >'.$row->$selections_table_name."</option>\n";
}
}
$r .= "</select>\n\n";
echo $r;
return $selection_name;
}
/**
* Handle selection action
*
* Determine if we need to perform an action to the current selection and do it in this case.
*
* @param integer the current selection id
* @param string prefix (cont_, etab_, firm_, ..)
* @param string selection prefix (cocs_, etes_, fifs_, ..)
*/
function handle_selection_actions( $selection_ID, $prefix, $prefix_sel )
{
// previous selection ID, need it to check for updating sel (no javascript possibility)
$previous_sel_ID = param( $prefix.'previous_sel_ID', 'integer', 0, true );
if( $selection_ID == $previous_sel_ID ) // the databse has to be updated
{ // The selected ID is the same than the edited one in the previous page
if( $selection_ID == 0 )
{ // A new selection must be created
$action = 'create';
}
elseif( $selection_ID >0 )
{ // An existing selection is being updated
$action = 'update';
}
// Get the selection name
$selection_name = param( 'selection_'.$prefix.'name', 'string', '', true );
// Do the slection action
selection_action( $action, $selection_ID, $selection_name, $prefix, $prefix_sel );
}
}
/**
* Manages the various database changes to make on selections
*
* @param string the action currently effectuated
* @param integer the current selection id
* @param string the current selection name
* @param string prefix (cont_, etab_, firm_, ..)
* @param string selection prefix (cocs_, etes_, fifs_, ..)
*/
function selection_action( $action, $selection_ID, $selection_name, $prefix, $prefix_sel )
{ // the form has been submitted to act on the database and not only to change the display
global $DB, $Messages, $confirm, $item_ID_list;
$items = param( $prefix.'items', 'array:string', array(), false ); // do NOT memorize // ?????????????
param( 'item_ID_list', 'string', '', false );
check_user_perm( 'selections', 'edit', true );
// Set global vars, selection_.prefix.ID, selection_.prefix_name
$selection_prefix_ID = 'selection_'.$prefix.'ID';
$selection_prefix_name = 'selection_'.$prefix.'name';
global $$selection_prefix_ID, $$selection_prefix_name;
// Moche ms bon...
$selections_table = 'T_'.substr($prefix,0,strlen($prefix)-1).'selections';
$sel_table = 'T_'.$prefix.substr($prefix,0,1).'sel';
$selections_table_name = substr($prefix,0,1).'sel_name';
$selections_table_id = substr($prefix,0,1).'sel_ID';
$sel_table_selection = $prefix_sel.$selections_table_id;
$sel_table_item = $prefix_sel.$prefix.'ID';
switch( $action )
{
// creation of a new selection
case 'create':
if( empty($selection_name) )
{ // No name provided:
$Messages->add( T_('Cannot create a selection with an empty name'), 'error' );
// Abord creation!
break;
}
$sql_selections = "INSERT INTO $selections_table ( $selections_table_name )
VALUES( ".$DB->quote($selection_name)." ) "; // construction of the query
$DB->query( $sql_selections ); // insertion of a new selection in the database
$selection_ID = $DB->insert_id; // id generated by the last sql query
if( !empty( $items ) )
{ // nothing must be inserted if no items are selected
$sql_sel = 'INSERT INTO '.$sel_table.'( '.$sel_table_item.', '.$sel_table_selection .') VALUES ';
$sel_array = array();
$i = 0;
foreach( $items as $item )
{ // construction of the sql query depending on selected values in the result table
$sel_array[$i++] = ' ('.$item.','.$selection_ID.' ) ';
}
$sql_sel .= implode( ',', $sel_array );
$DB->query( $sql_sel ); // insertion of the relation between selections and items in the database
}
// Set $selection_.$prefix.ID var
$sel_prefix_ID = 'selection_'.$prefix.'ID';
$$sel_prefix_ID = $selection_ID;
// Set $selection_.$prefix.name var
$sel_prefix_name = 'selection_'.$prefix.'name';
$$sel_prefix_name = $selection_name;
$Messages->add( T_('Selection created.'), 'success' );
break;
case 'edit':
case 'update':
// update of an existing selection
$DB->begin();
if( empty($selection_name) )
{ // No name provided:
$Messages->add( T_('Please provide a selection name.'), 'error' );
}
else
{ // Update name:
$sql_selections = "UPDATE $selections_table
SET $selections_table_name = ".$DB->quote($selection_name)."
WHERE $selections_table_id = $selection_ID"; // construction of the update query
$DB->query( $sql_selections );
}
if( preg_match( '#[0-9,]+#', $item_ID_list ) )
{ // check the format of the item list to avoid sql injection
$sql_delete = 'DELETE FROM '.$sel_table.' WHERE '.$sel_table_selection.' = '.$selection_ID
.' AND '.$sel_table_item.' IN ('.$item_ID_list.')'; // deletion of the former db entries
$DB->query( $sql_delete );
$Messages->add( T_('Obsolete selection entries deleted.'), 'success' );
}
if( !empty( $items ) )
{ // there have been some items selected in the result table: they must be inserted into the database
$sql_sel = 'INSERT INTO '.$sel_table.'( '.$sel_table_item.', '.$sel_table_selection .') VALUES ';
$sel_array = array();
foreach( $items as $item )
{ // construction of the sql query depending on selected values in the result table
$sel_array[] = ' ( '.$item.', '.$selection_ID.' ) ';
}
$sql_sel .= implode( ',', $sel_array );
$DB->query( $sql_sel ); // insertion of the relation between selections and items in the database
$Messages->add( T_('New selections entries inserted.'), 'success' );
}
$DB->commit();
break;
case 'copy':
// creation of a new selection with the same name
$sql_selections = 'INSERT INTO '.$selections_table.'('.$selections_table_name.
') VALUES( "'.$selection_name.'" )';
$DB->query( $sql_selections );
$Messages->add( T_('Selection copied.'), 'success' );
$new_selection_ID = $DB->insert_id;// gets the new selection id
// creation of the links between the new selection and the selected items
$sql_sel = 'INSERT INTO '.$sel_table.'( '.$sel_table_item.', '.$sel_table_selection.' ) '
.'SELECT '.$sel_table_item.', '.$new_selection_ID.' FROM '.$sel_table.' WHERE '
.$sel_table_selection.'='.$selection_ID;
$DB->query( $sql_sel );
$Messages->add( T_('Selection links copied.'), 'success' );
$selection_ID = $new_selection_ID;
break;
case 'delete':
// deletion of the selection
if( !$confirm )
{ // ask for confirmation before deleting
?>
<div class="panelinfo">
<h3><?php printf( T_('Delete selection «%s»?'), $selection_name )?></h3>
<p><?php echo T_('Warning').': '.T_('Cascading deletes!') ?></p>
<p><?php echo T_('THIS CANNOT BE UNDONE!') ?></p>
<p>
<?php
$Form = new Form( regenerate_url('', '', '', '&'), 'form_confirm', 'post', '' );
$action = '';
$Form->begin_form( 'inline' );
$Form->hidden( 'action', 'delete' );
$Form->hidden( 'selection_ID', $selection_ID );
$Form->hidden( 'selection_name', $selection_name );
$Form->hidden( 'confirm', 1 );
$Form->button( array( 'submit', '', T_('I am sure!'), 'DeleteButton btn-danger' ) );
$Form->end_form();
unset( $Form );
$Form = new Form( regenerate_url('', '', '', '&'), 'form_cancel', 'post', '' );
$Form->begin_form( 'inline' );
$Form->button( array( 'submit', '', T_('CANCEL'), 'CancelButton' ) );
$Form->end_form();
?>
</p>
</div>
<?php
}
else
{ // the deletion has been confirmed
$sql_sel = 'DELETE FROM '.$sel_table.' WHERE '.$sel_table_selection.'='.$selection_ID;
$DB->query( $sql_sel );// deletion of the links between the selection and the selected items
$Messages->add( T_('Selection attachments deleted.'), 'success' );
$sql_selections = 'DELETE FROM '.$selections_table.' WHERE '.$selections_table_id.'='.$selection_ID;
$DB->query( $sql_selections );// deletion of the selection
$Messages->add( T_('Selection deleted.'), 'success' );
}
$selection_ID = -1;
break;
default:
break;
}
return $selection_ID;
}
?>