• This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn more.

Repeat of entry

Mythotical

Well-known member
#1
I am attempting to take a post count, multiply it, divide it, etc then insert that new total into a separate table.

Here is a screenshot: http://gyazo.com/0c51285871b289a9eca7f335e740f7ef

Steve - Has over 2k posts
Test - Has 0 posts

Therefore lifetime and total points for Test should be 0 no matter what. But the points from Steve keep getting inserted under each username.

Soooo now my code, hope you can make heads or tails of it as I have commented out lines, I don't like to delete lines until I'm done with that feature.

PHP:
<?php

class xShop_ControllerAdmin_Index_Convert extends XenForo_ControllerAdmin_Abstract
{
//    Public $perms;

    public function actionIndex()
    {
        $options = XenForo_Application::get('options');
        $db = XenForo_Application::get('db');

        $xs_sub_total = $db->fetchOne('
            SELECT COUNT(*) 
            FROM xf_user');
        
    /*    $xs_total_left = $db->fetchAll('
            SELECT user.user_id, COUNT(*) AS pointcount
            FROM xf_user AS user
            LEFT JOIN xshop_points AS pts
            ON user.user_id = pts.user_id
            GROUP BY user.user_id');*/
        
        //$xs_insert_total = $xs_sub_total-$xs_total_left;

        $xs_subs = $db->fetchAll('
            SELECT user_id, message_count
            FROM xf_user ORDER BY user_id DESC');
                    
            foreach ($xs_subs AS $xs_sub)
            {
                if($xs_sub['message_count'] == '0'){
                    $new_point_total = 0;
                } else {
                $new_point_total = round($xs_sub['message_count']*$options->xshop_convert_rate/15*2-50);
                }
                $userid = $xs_sub['user_id'];
                //$this->_insertData($xs_sub, $points_insert, $new_point_total);
            }

            $viewParams = array(
                'xs_sub_total' => $xs_sub_total,
                'new_point_total' => $new_point_total,
                'userid' => $userid,
                //'xs_insert_total' => $xs_insert_total,
                //'points_insert' => $points_insert,
                'xs_sub' => $xs_sub
            );
        
        return $this->responseView('xShop_ViewAdmin_Convert', 'xshop_convert', $viewParams);
    }

    public function actionConversion()
    {
        $boardTotals = $this->getModelFromCache('XenForo_Model_DataRegistry')->get('boardTotals');
        if (!$boardTotals)
        {
            $boardTotals = $this->getModelFromCache('XenForo_Model_Counters')->rebuildBoardTotalsCounter();
        }
        
        $this->_assertPostOnly();
            
        $options = XenForo_Application::get('options');
        $db = XenForo_Application::get('db');

        $points_insert = $this->_input->filter(array(
            'user_id' => XenForo_Input::UINT,
            'message_count' => XenForo_Input::UINT,
            'new_point_total' => XenForo_Input::UINT
        ));
        
        $lang = $db->fetchAll('
            SELECT language_id
            FROM xf_language WHERE language_id = ?', 1);
        
        $xs_sub_total = $db->fetchOne('
            SELECT COUNT(*) 
            FROM xf_user');
        
    /*    $xs_total_left = $db->fetchAll('
            SELECT user.user_id, COUNT(*) AS pointcount
            FROM xf_user AS user
            LEFT JOIN xshop_points AS pts
            ON user.user_id = pts.user_id
            GROUP BY user.user_id');*/
        
        //$xs_insert_total = $xs_sub_total-$xs_total_left;

        $page = max(1, $this->_input->filterSingle('page', XenForo_Input::UINT));
        $perPage = 250;

        $xs_subs = $db->fetchAll('
            SELECT user_id, message_count
            FROM xf_user ORDER BY user_id DESC');
                    
        $xs_subss = array(
            'page' => $page,
            'perPage' => $perPage
        );

            foreach ($xs_subs AS $xs_sub)
            {
                if($xs_sub['message_count'] == '0'){
                    $new_point_total = 0;
                } else {
                $new_point_total = round($xs_sub['message_count']*$options->xshop_convert_rate/15*2-50);
                }
                $userid = $xs_sub['user_id'];
                $this->_insertData($xs_sub, $points_insert, $new_point_total);
            }

            $viewParams = array(
                'xs_sub_total' => $xs_sub_total,
                'new_point_total' => $new_point_total,
                //'xs_insert_total' => $xs_insert_total,
                'points_insert' => $points_insert,
                'userid' => $userid,
                'completed' => ($page - 1) * $perPage + count($xs_sub_total),
                'nextPage' => $page + 1,
                'xs_sub' => $xs_sub,
                'boardTotals' => $boardTotals
            );

        return $this->responseView('xShop_ViewAdmin_ConvertConversion', 'xshop_converting', $viewParams);
    }        

    public function _insertData(array $points_insert)
    {
        $this->_assertPostOnly();

        $dwInput = $this->_input->filter(array(
            'points_id' => XenForo_Input::UINT,
            'user_id' => XenForo_Input::UINT,
            'points_total' => XenForo_Input::UINT,
            'points_earned' => XenForo_Input::UINT,
            'new' => XenForo_Input::UINT
        ));

        $dw = XenForo_DataWriter::create('xShop_DataWriter_Convert');
        if ($dwInput['points_id'])
            $dw->setExistingData($dwInput['points_id']);
        
        $dw->set('points_id', $dwInput['points_id']);
        $dw->set('user_id', $points_insert['user_id']);
        $dw->set('points_total', $dwInput['new']);
        $dw->set('points_earned', $dwInput['new']);
        $dw->save();
        
        $redirectType = ($dwInput['points_id'] ?
            XenForo_ControllerResponse_Redirect::RESOURCE_UPDATED :
            XenForo_ControllerResponse_Redirect::RESOURCE_CREATED);
            
        return $this->responseRedirect(
            $redirectType,
            XenForo_Link::buildAdminLink('xshop/points')
        );
    }
}
xshop_convert template
HTML:
<xen:title>Conversion Tool</xen:title>
    <div class="selection">
        <h2 class="subHeading">Conversion</h2>
            <br />
            <p>You are about to perform a conversion process that will convert all current post counts to {$xenOptions.xshop_currency}. This process can only be ran once and will cause any points accumulated so far to get doubled. This process should be ran right after the install.</p>
            <br />
{xen:raw $new_point_total}
            <br />
        <xen:include template="xshop_footer" />
        <xen:form action="{xen:adminlink xshop/convert/conversion}">        
            <input type="hidden" name="user_id" value="{$xs_subs.user_id}" />
            <input type="hidden" name="new" value="{$new_point_total}" />
            <input type="hidden" name="message_count" value="{$xs_subs.message_count} />
            <xen:submitunit save="Continue with Conversion?" />
        </xen:form>
    </div>

<xen:require css="filter_list.css" />
<xen:require js="js/xenforo/filter_list.js" />
xshop_converting template
HTML:
<xen:title>Converting post count to {$xenOptions.xshop_currency}...</xen:title>

<xen:form action="{xen:adminlink xshop/points}" id="conversionTool">
    
    <p>
        Converting users post count... {xen:number $completed} / {xen:number $xs_sub_total}
        <img src="@imagePath/widgets/ajaxload.info_000000_facebook.gif" alt="Loading..." id="loadingImage" style="display:none" />
    </p>
    <input type="submit" value="Continue" class="button primary" id="insertData" />
    
    <input type="hidden" name="page" value="{$nextPage}" />
        
    <input type="hidden" name="_xfConfirm" value="1" />
    
</xen:form>

<script type="text/javascript">
    $('#loadingImage').show();
</script>
 

Jake Bunce

XenForo moderator
Staff member
#2
Therefore lifetime and total points for Test should be 0 no matter what. But the points from Steve keep getting inserted under each username.
Your foreach loop is overwriting those vars at each iteration:

Code:
            foreach ($xs_subs AS $xs_sub)
            {
                if($xs_sub['message_count'] == '0'){
                    $new_point_total = 0;
                } else {
                $new_point_total = round($xs_sub['message_count']*$options->xshop_convert_rate/15*2-50);
                }
                $userid = $xs_sub['user_id'];
                //$this->_insertData($xs_sub, $points_insert, $new_point_total);
            }
That means those vars will contain the values for the last user that is processed by the foreach. You should use an array that is indexed by user_id, or even make $xs_sub a reference variable (foreach ($xs_subs AS &$xs_sub)) and then set a new index during the foreach.
 

Mythotical

Well-known member
#3
The funny thing is that it inserts the userid's just fine. Aside from that, the method you mentioned I have never used. Do you have an in depth explanation or example?
 

Jake Bunce

XenForo moderator
Staff member
#6
Example of foreach using reference parameter:

XenForo_ControllerPublic_Thread::actionIndex

Code:
		foreach ($posts AS &$post)
		{
			$post['position_on_page'] = ++$pagePosition;

			$postModOptions = $postModel->addInlineModOptionToPost(
				$post, $thread, $forum, $permissions
			);
			$inlineModOptions += $postModOptions;

			$post = $postModel->preparePost($post, $thread, $forum, $permissions);

			if ($post['post_date'] > $maxPostDate)
			{
				$maxPostDate = $post['post_date'];
			}

			if ($post['isDeleted'])
			{
				$deletedPosts++;
			}
			if ($post['isModerated'])
			{
				$moderatedPosts++;
			}

			if (!$firstUnreadPostId && $post['isNew'])
			{
				$firstUnreadPostId = $post['post_id'];
			}
		}
&$post is a reference, and it sets position_on_page for each post as the foreach iterates through $posts array.