Seditio Source
Root |
./othercms/b2evolution_7.2.3/inc/polls/model/_poll.class.php
<?php
/**
 * This file implements the Poll class.
 *
 * This file is part of the b2evolution/evocms project - {@link http://b2evolution.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/}.
*
 * @license http://b2evolution.net/about/license.html GNU General Public License (GPL)
 *
 * @package evocore
 */
if( !defined('EVO_MAIN_INIT') ) die( 'Please, do not access this page directly.' );

load_class( '_core/model/dataobjects/_dataobject.class.php', 'DataObject' );


/**
 * Poll Class
 *
 * @package evocore
 */
class Poll extends DataObject
{
    var
$owner_user_ID;
    var
$question_text;
    var
$max_answers;

   
/**
     * @var array PollOption objects
     */
   
var $poll_options;

   
/**
     * @var array with keys:
     *       - 'votes' - a number of votes of this Poll from all voters,
     *       - 'voters' - a number of users which voted on at least one option of this poll.
     */
   
var $vote_nums = NULL;

   
/**
     * Constructor
     *
     * @param object table Database row
     */
   
function __construct( $db_row = NULL )
    {
       
// Call parent constructor:
       
parent::__construct( 'T_polls__question', 'pqst_', 'pqst_ID' );

        if(
$db_row != NULL )
        {    
// Get poll data from DB:
           
$this->ID = $db_row->pqst_ID;
           
$this->owner_user_ID = $db_row->pqst_owner_user_ID;
           
$this->question_text = $db_row->pqst_question_text;
           
$this->max_answers = $db_row->pqst_max_answers;
        }
        else
        {    
// Set default poll data for new poll:
           
if( is_logged_in() )
            {
                global
$current_User;
               
$this->set( 'owner_user_ID', $current_User->ID );
               
$this->set( 'max_answers', 1 );
            }
        }
    }


   
/**
     * Get delete cascade settings
     *
     * @return array
     */
   
static function get_delete_cascades()
    {
        return array(
                array(
'table' => 'T_polls__option', 'fk' => 'popt_pqst_ID', 'msg' => T_('%d poll options') ),
                array(
'table' => 'T_polls__answer', 'fk' => 'pans_pqst_ID', 'msg' => T_('%d poll answers') ),
            );
    }


   
/**
     * Load data from Request form fields.
     *
     * @return boolean true if loaded data seems valid.
     */
   
function load_from_Request()
    {
        global
$current_User;

       
// Owner:
       
if( check_user_perm( 'polls', 'edit' ) )
        {    
// Update the owner if current user has a permission to edit all polls:
           
$pqst_owner_login = param( 'pqst_owner_login', 'string', NULL );
           
param_check_not_empty( 'pqst_owner_login', T_('Please enter the owner\'s login.') );
            if( ! empty(
$pqst_owner_login ) )
            {    
// If the login is entered:
               
$UserCache = & get_UserCache();
               
$owner_User = & $UserCache->get_by_login( $pqst_owner_login );
                if( empty(
$owner_User ) )
                {    
// Wrong entered login:
                   
param_error( 'pqst_owner_login', sprintf( T_('User &laquo;%s&raquo; does not exist!'), $pqst_owner_login ) );
                }
                else
                {    
// Set new login:
                   
$this->set( 'owner_user_ID', $owner_User->ID );
                   
$this->owner_User = & $owner_User;
                }
            }
        }
        elseif( empty(
$this->ID ) )
        {    
// Set owner user ID on creating new poll:
           
$this->set( 'owner_user_ID', $current_User->ID );
           
$this->owner_User = & $current_User;
        }

       
// Question:
       
param( 'pqst_question_text', 'string', false );
       
param_check_not_empty( 'pqst_question_text', T_('Please enter the text for the poll\'s question.') );
       
$this->set_from_Request( 'question_text' );

       
// Maximum number of answers:
       
$pqst_max_answers = param( 'pqst_max_answers', 'integer', 1 );
        if( empty(
$this->ID ) )
        {
           
$options = array();
           
$answer_options = param( 'answer_options', 'array:string', array() );
            foreach(
$answer_options as $answer_option_text )
            {
                if( empty(
$answer_option_text ) )
                {    
// Skip empty option:
                   
continue;
                }

               
$options[] = $answer_option_text;
            }
        }
        else
        {
           
$options = $this->get_poll_options();
        }

        if(
$pqst_max_answers > count( $options ) )
        {
           
param_error( 'pqst_max_answers', T_('Maximum allowed answers must not exceed total number of answer options.') );
        }
        else
        {
           
$this->set_from_Request( 'max_answers' );
        }

        return !
param_errors_detected();
    }


   
/**
     * Insert object into DB based on previously recorded changes.
     *
     * @return boolean true on success
     */
   
function dbinsert()
    {
        global
$DB;

       
$DB->begin( 'SERIALIZABLE' );

        if(
parent::dbinsert() )
        {
// The poll was inserted successful:

            // Insert the entered answer options:
           
$answer_options = param( 'answer_options', 'array:string', array() );
           
$answer_option_order = 1;
            foreach(
$answer_options as $answer_option_text )
            {
                if( empty(
$answer_option_text ) )
                {    
// Skip empty option:
                   
continue;
                }

               
$new_PollOption = new PollOption();
               
$new_PollOption->set( 'pqst_ID', $this->ID );
               
$new_PollOption->set( 'option_text', $answer_option_text );
               
$new_PollOption->set( 'order', $answer_option_order );
                if( !
$new_PollOption->dbinsert() )
                {    
// Rollback if the poll option could not be inserted:
                   
$DB->rollback();
                    return
false;
                }

               
$answer_option_order++;
            }

           
$DB->commit();
            return
true;
        }

       
// Could not insert the poll object:
       
$DB->rollback();
        return
false;
    }


   
/**
     * Get name of the question. It is a string as first 200 chars of the question text:
     *
     * @return string
     */
   
function get_name()
    {
        return
strmaxlen( $this->get( 'question_text' ), 200 );
    }


   
/**
     * Get user object of this poll owner
     *
     * @return object User
     */
   
function & get_owner_User()
    {
        if( ! isset(
$this->owner_User ) )
        {    
// Get the owner User only first time:
           
$UserCache = & get_UserCache();
           
$this->owner_User = & $UserCache->get_by_ID( $this->owner_user_ID );
        }

        return
$this->owner_User;
    }


   
/**
     * Get numbers of votes and voters for this Poll
     *
     * @param string|NULL NULL - to return an array of all possible numbers,
     *                    'votes' - to return a number of votes of this Poll from all voters,
     *                    'voters' - to return a number of users which voted on at least one option of this poll.
     * @return array|integer Depends on param $type
     */
   
function get_vote_nums( $type = NULL )
    {
        global
$DB;

        if(
$this->vote_nums === NULL )
        {    
// Get from DB once and store in cache array:
           
$nums_SQL = new SQL( 'Get a count of votes and voters for the edited poll #'.$this->ID );
           
$nums_SQL->SELECT( 'COUNT( pans_pqst_ID ) AS votes, COUNT( DISTINCT pans_user_ID ) AS voters' );
           
$nums_SQL->FROM( 'T_polls__answer' );
           
$nums_SQL->WHERE( 'pans_pqst_ID = '.$this->ID );
           
$this->vote_nums = $DB->get_row( $nums_SQL, ARRAY_A );
        }

        if(
$type === NULL )
        {    
// Get all numbers:
           
return $this->vote_nums;
        }
        else
        {    
// Get a specific number:
           
if( ! isset( $this->vote_nums[ $type ] ) )
            {
               
debug_die( 'Wrong param type "'.$type.'" for Poll::get_vote_nums()' );
            }
            return
$this->vote_nums[ $type ];
        }
    }


   
/**
     * Get all options of this poll
     *
     * @return array PollOption objects
     */
   
function get_poll_options()
    {
        if( empty(
$this->ID ) )
        {    
// New creating poll doesn't have the options, Return empty array:
           
return array();
        }

        if(
$this->poll_options === NULL )
        {    
// Get options from DB only first time, and store them in cache array:
           
global $DB;

           
// Get numbers of votes and voters for the edited poll:
           
$poll_voters_num = $this->get_vote_nums( 'voters' );
            if(
$poll_voters_num == 0 )
            {    
// To don't devide by zero
               
$poll_voters_num = 1;
            }

           
$SQL = new SQL( 'Get all options of this poll' );
           
$SQL->SELECT( 'popt_ID AS ID, popt_pqst_ID AS pqst_ID, popt_option_text AS option_text,' );
           
//$SQL->SELECT_add( 'COUNT( * ) AS answers_count,' );
           
$SQL->SELECT_add( 'ROUND( COUNT( pans_pqst_ID ) / '.$poll_voters_num.' * 100 ) AS percent' );
           
$SQL->FROM( 'T_polls__option' );
           
$SQL->FROM_add( 'LEFT JOIN T_polls__answer ON pans_popt_ID = popt_ID' );
           
$SQL->WHERE( 'popt_pqst_ID = '.$this->ID );
           
$SQL->GROUP_BY( 'popt_ID' );
           
$SQL->ORDER_BY( 'popt_order' );

           
$this->poll_options = $DB->get_results( $SQL );
        }

        return
$this->poll_options;
    }


   
/**
     * Get max percent of poll options
     *
     * @return integer Max percent
     */
   
function get_max_poll_options_percent()
    {
       
// Get all poll options:
       
$poll_options = $this->get_poll_options();

       
$max_percent = 0;

        foreach(
$poll_options as $poll_option )
        {    
// Find max percent in all poll options:
           
if( $poll_option->percent > $max_percent )
            {
               
$max_percent = $poll_option->percent;
            }
        }

        return
$max_percent;
    }


   
/**
     * Get votes of the user
     *
     * @param integer User ID of specific user
     * @return array|boolean Poll option IDs OR FALSE if current user didn't vote on this poll yet
     */
   
function get_user_vote( $user_ID = NULL )
    {
        global
$current_User, $DB;

        if( ! empty(
$user_ID ) )
        {
           
$UserCache = & get_UserCache();
           
$user = & $UserCache->get_by_ID( $user_ID, false, false );
        }
        elseif(
is_logged_in() )
        {
           
$user = $current_User;
        }

        if( empty(
$user ) )
        {
            return
false;
        }

       
// Get answer of user for this poll:
       
$poll_option_SQL = new SQL( 'Get answer of current user on the poll question' );
       
$poll_option_SQL->SELECT( 'pans_popt_ID' );
       
$poll_option_SQL->FROM( 'T_polls__answer' );
       
$poll_option_SQL->WHERE( 'pans_pqst_ID = '.$this->ID );
       
$poll_option_SQL->WHERE_and( 'pans_user_ID = '.$user->ID );
       
$poll_option_IDs = $DB->get_col( $poll_option_SQL );

        return empty(
$poll_option_IDs ) ? false : $poll_option_IDs;
    }


   
/**
     * Clears all votes of the user
     *
     * @param integer User ID of specific user
     */
   
function clear_user_votes( $user_ID = NULL )
    {
        global
$current_User, $DB;

        if( ! empty(
$user_ID ) )
        {
           
$UserCache = & get_UserCache();
           
$user = & $UserCache->get_by_ID( $user_ID, false, false );
        }
        elseif(
is_logged_in() )
        {
           
$user = $current_User;
        }

        if( empty(
$user ) )
        {
            return
false;
        }

       
$DB->query( 'DELETE FROM T_polls__answer WHERE pans_user_ID = '.$user->ID.' AND pans_pqst_ID = '.$this->ID );

        return
true;
    }
}

?>