XF 2.0 Check for trophies that users should be un-awarded/revoked

Rick7C2

Member
I see the Trophy cron that will award trophies to users that have met the requirements but I need the opposite as well.

I need a cron that will check a users trophies and revert if they no longer meet the conditions.

How do I do this?
 

Rick7C2

Member
How do I rewrite this code so that it removes the data it adds?

PHP:
$inserted = $this->db()->insert('xf_user_trophy', [
            'user_id' => $user->user_id,
            'trophy_id' => $trophy->trophy_id,
            'award_date' => \XF::$time
 

Rick7C2

Member
Can someone give me an example of
db()->delete

After looking through XF2 code I found in src/XF/Db/AbstractAdapter.php

PHP:
public function delete($table, $where, $params = [], $modifier = '', $order = '', $limit = 0)
    {
        $res = $this->query(
            "DELETE $modifier FROM `$table` WHERE " . ($where ? $where : '1=1')
            . ($order ? " ORDER BY $order" : '')
            . ($limit ? ' LIMIT ' . intval($limit) : ''),
            $params
        );
        return $res->rowsAffected();
    }
I just don't understand how I call it.

I think I need to do something like...

PHP:
$revoked = $this->db()->delete('xf_user_trophy', [
            'user_id' = $user->user_id,
            'trophy_id' = $trophy->trophy_id
        ];

I just need it to run this command but with working vars $user->user_id and $trophy->trophy_id

Code:
DELETE FROM `xf_user_trophy` WHERE `xf_user_trophy`.`user_id` = $user->user_id AND `xf_user_trophy`.`trophy_id` = $trophy->trophy_id
 

Rick7C2

Member
Ok so I got this working the way I wanted by editing the core XF2 files doing the following edits...

src/XF/Repository/Trophy.php #See my START and END Comments for additions

PHP:
<?php

namespace XF\Repository;

use XF\Mvc\Entity\Finder;
use XF\Mvc\Entity\Repository;

class Trophy extends Repository
{
    /**
     * @return Finder
     */
    public function findTrophiesForList()
    {
        return $this->finder('XF:Trophy')->order('trophy_points');
    }

    /**
     * @return Finder
     */
    public function findUsersTrophies(array $userIds)
    {
        return $this->finder('XF:UserTrophy')
            ->where('user_id', $userIds)
            ->setDefaultOrder(['user_id', 'award_date']);
    }

    /**
     * @param integer $userId
     * @return Finder
     */
    public function findUserTrophies($userId)
    {
        return $this->finder('XF:UserTrophy')
            ->where('user_id', $userId)
            ->setDefaultOrder('award_date', 'DESC');
    }

    /**
     * @param \XF\Entity\User $user
     * @param \XF\Entity\UserTrophy[] $userTrophies
     * @param \XF\Entity\Trophy[] $trophies
     * @return int
     */
    public function updateTrophiesForUser(\XF\Entity\User $user, $userTrophies = null, $trophies = null)
    {
        if ($userTrophies === null)
        {
            $userTrophies = $this->findUserTrophies($user->user_id)->fetch();
        }

        if ($trophies === null)
        {
            $trophies = $this->findTrophiesForList()->fetch();
        }

        $awarded = 0;

        foreach ($trophies AS $trophy)
        {
            if (isset($userTrophies[$trophy->trophy_id]))
            {
                continue;
            }

            $userCriteria = $this->app()->criteria('XF:User', $trophy->user_criteria);
            $userCriteria->setMatchOnEmpty(false);
            if ($userCriteria->isMatched($user))
            {
                $this->awardTrophyToUser($trophy, $user);
            }
            // Revoke Trophies for Users that no longer meet requirements. START
            else
            {
                $this->revokeTrophyToUser($trophy, $user);
            }
            //    Revoke Trophies for Users that no longer meet requirements. END   
        }

        return $awarded;
    }

    public function awardTrophyToUser(\XF\Entity\Trophy $trophy, \XF\Entity\User $user)
    {
        $inserted = $this->db()->insert('xf_user_trophy', [
            'user_id' => $user->user_id,
            'trophy_id' => $trophy->trophy_id,
            'award_date' => \XF::$time
        ], false, false, 'IGNORE');

        if ($inserted)
        {
            $user->fastUpdate('trophy_points', $user->trophy_points + $trophy->trophy_points);

            /** @var \XF\Repository\UserAlert $alertRepo */
            $alertRepo = $this->repository('XF:UserAlert');
            $alertRepo->alertFromUser($user, $user, 'trophy', $trophy->trophy_id, 'award');

            return true;
        }
        else
        {
            return false;
        }
    }
    
    // Revoke Trophies for Users that no longer meet requirements. START
    public function revokeTrophyToUser(\XF\Entity\Trophy $trophy, \XF\Entity\User $user)
    {
        $revoked = $this->db()->delete('xf_user_trophy', 'user_id = ? AND trophy_id = ?', [$user->user_id, $trophy->trophy_id]);

        if ($revoked)
        {
            $user->fastUpdate('trophy_points', $user->trophy_points - $trophy->trophy_points);

            /** @var \XF\Repository\UserAlert $alertRepo */
            //$alertRepo = $this->repository('XF:UserAlert');
            //$alertRepo->alertFromUser($user, $user, 'trophy', $trophy->trophy_id, 'award');

            return true;
        }
        else
        {
            return false;
        }
    }
    // Revoke Trophies for Users that no longer meet requirements. END

    public function recalculateUserTrophyPoints(\XF\Entity\User $user)
    {
        $points = intval($this->db()->fetchOne("
            SELECT SUM(trophy.trophy_points)
            FROM xf_user_trophy AS user_trophy
            INNER JOIN xf_trophy AS trophy ON (user_trophy.trophy_id = trophy.trophy_id)
            WHERE user_trophy.user_id = ?
        ", $user->user_id));

        $user->fastUpdate('trophy_points', $points);

        return $points;
    }
}
@Brogan Did I miss anything? Could this be officially added to XF2?

If not please help me to make this an addon.
 

Joe Link

Well-known member
Anyone know of an add-on that can do this? I'm really surprised trophies aren't removed once the member no longer meets the criteria...
 
Top