railpage/railpagecore

View on GitHub
lib/Images/Screener.php

Summary

Maintainability
F
3 days
Test Coverage
<?php

/**
 * Review images submitted to the pool
 * @since Version 3.10.0
 * @package Railpage
 * @author Michael Greenhill
 */

namespace Railpage\Images;

use DateTime;
use Exception;
use Railpage\AppCore;
use Railpage\Debug;
use Railpage\Url;
use Railpage\Users\User;
use Railpage\Users\Factory as UserFactory;
use Railpage\Users\Utility\AvatarUtility;

class Screener extends AppCore {
    
    /**
     * Get unreviewed images
     * @since Version 3.10.0
     * @param int $page
     * @param int $itemsPerPage
     * @return array
     */
    
    public function getUnreviewedImages($page = 1, $itemsPerPage = 25) {
        
        if (!$this->User instanceof User) {
            throw new Exception("Cannot find unreviewed images - no user has been set");
        }
        
        $query = "SELECT SQL_CALC_FOUND_ROWS image.id, image.title, image.user_id 
                    FROM image 
                    WHERE image.id NOT IN ( 
                        SELECT f.image_id 
                        FROM image_flags AS f
                        WHERE f.image_id = image.id 
                    ) 
                    AND image.id NOT IN (
                        SELECT s.image_id
                        FROM image_flags_skip AS s
                        WHERE s.user_id = ?
                    )
                    AND image.hidden = 0 
                    ORDER BY image.id DESC 
                    LIMIT ?, ?";
        
        $params = [ 
            $this->User->id,
            ($page - 1) * $itemsPerPage, 
            $itemsPerPage 
        ];
        
        $return = array(
            "page" => $page, 
            "items_per_page" => $itemsPerPage, 
            "total" => 0,
            "images" => array()
        );
        
        $result = $this->db->fetchAll($query, $params); 
        $return['total'] = $this->db->fetchOne("SELECT FOUND_ROWS()");
        
        $return['images'] = $result;
        
        return $return;
        
    }
    
    /**
     * Review an image
     * @since Version 3.10.0
     * @param \Railpage\Images\Image $imageObject
     * @param \Railpage\Users\User $userObject
     * @param boolean $publish
     * @param boolean $pick Does the screener think this is an exceptional photograph?
     * @return \Railpage\Images\Screener
     */
    
    public function reviewImage(Image $imageObject, User $userObject, $publish = 0, $pick = 0) {
        
        $publish = (bool) intval($publish);
        $pick = (bool) intval($pick); 
        
        // If the screener hinks this is a worthy photo, why shouldn't we publish it?
        if ($pick == true) {
            $publish = true;
        }
        
        $query = sprintf(
            "INSERT INTO image_flags (
                image_id, published, screened, screened_by, screened_on, screened_pick, rejected
            ) VALUES (
                %d, %d, %d, %d, NOW(), %d, %d
            ) ON DUPLICATE KEY UPDATE 
                published = VALUES(published), screened_by = VALUES(screened_by), 
                screened_on = NOW(), screened_pick = VALUES(screened_pick), rejected = VALUES(rejected)",
            $this->db->quote(intval($imageObject->id)), 
            $publish, 
            1, 
            $this->db->quote(intval($userObject->id)), 
            $pick, 
            !$publish
        );
        
        $this->db->query($query); 
        
        /**
         * Delete it from the review skip table
         */
        
        $where = [ 
            "image_id = ?" => $imageObject->id
        ];
        
        $this->db->delete("image_flags_skip", $where);
        
        if ($publish) {
            $imageObject = Utility\Updater::updateAuthor($imageObject);
        }
        
        return $this;
        
    }
    
    /**
     * Skip reviewing this image
     * @since Version 3.10.0
     * @param \Railpage\Images\Image $imageObject
     * @param \Railpage\Users\User $userObject
     * @return \Railpage\Images\Screener
     */
    
    public function skipImage(Image $imageObject, User $userObject) {
        
        $query = sprintf(
            "INSERT INTO image_flags_skip ( 
                `image_id`, `user_id`, `date`
            ) VALUES (
                %d, %d, NOW()
            ) ON DUPLICATE KEY UPDATE
                `date` = NOW()",
            $this->db->quote(intval($imageObject->id)), 
            $this->db->quote(intval($userObject->id))
        );
        
        $this->db->query($query); 
        
        return $this;
        
    }
    
    /**
     * Get a list of users who have skipped reviewing this photo
     * @since Version 3.10.0
     * @param \Railpage\Images\Image $imageObject
     * @return array
     */
    
    public function getSkippedBy(Image $imageObject) {
        
        $query = "SELECT u.username, u.user_id FROM nuke_users AS u LEFT JOIN image_flags_skip AS p ON p.user_id = u.user_id WHERE p.image_id = ?";
        
        $rs = $this->db->fetchAll($query, $imageObject->id); 
        return $rs;
        
    }
    
    /**
     * Undo the last screening by this user
     * @since Version 3.10.0
     * @return \Railpage\Images\Screener
     */
    
    public function undo() {
        
        if (!$this->User instanceof User) {
            throw new Exception("No valid user has been set");
        }
        
        $id = $this->db->fetchOne("SELECT image_id FROM image_flags WHERE screened_by = ? ORDER BY screened_on DESC LIMIT 1", $this->User->id);
        
        if (!filter_var($id, FILTER_VALIDATE_INT)) {
            return $this;
        }
        
        $where = [ "image_id = ?" => $id ];
        $this->db->delete("image_flags", $where);
        
        return $this;
        
    }
    
    /**
     * Delete an image 
     * @since Version 3.10.0
     * @param int|string $id
     * @param string $provider
     */
    
    public function deleteImage($id, $provider = null) {
        
        if ($provider == null) {
            $where = [ "id = ?" => $id ];
            $this->db->delete("image", $where); 
            
            return $this;
        }
        
        $where = [ 
            "photo_id = ?" => $id, 
            "provider" => $provider
        ]; 
        
        $this->db->delete("image", $where); 
        
        return $this;
        
    }
    
    /**
     * Get the screener of the selected image
     * @since Version 3.10.0
     * @param \Railpage\Images\Image $imageObject
     * @return array
     */
    
    public function getImageScreener(Image $imageObject) {
        
        $query = "SELECT f.*, f.screened_by AS user_id, u.username, u.user_avatar, CONCAT('/user/', f.screened_by) AS url FROM image_flags AS f LEFT JOIN nuke_users AS u ON f.screened_by = u.user_id WHERE image_id = ?";
        
        $row = $this->db->fetchRow($query, $imageObject->id); 
        
        $av = $row['user_avatar'];
        
        $row['user_avatar'] = [
            "tiny" => AvatarUtility::Format($av, 25, 25),
            "thumb" => AvatarUtility::Format($av, 50, 50),
            "small" => AvatarUtility::Format($av, 75, 75),
            "medium" => AvatarUtility::Format($av, 100, 100)
        ];
        
        return $row;
        
    }
    
    /**
     * Get the list of screeners
     * @since Version 3.10.0
     * @return array
     */
    
    public function getScreeners() {
        
        $query = "SELECT u.user_id, u.username, CONCAT('/user/', u.user_id) AS url, COUNT(*) AS num
            FROM image_flags AS f
            LEFT JOIN nuke_users AS u ON f.screened_by = u.user_id 
            WHERE u.user_id NOT IN (2)
            GROUP BY f.screened_by
            ORDER BY u.username";
        
        return $this->db->fetchAll($query); 
        
    }
    
    /**
     * Get rejected images
     * @since Version 3.10.0
     * @param int $page
     * @param int $itemsPerPage
     * @return array
     */
    
    public function getRejectedImages($page = 1, $itemsPerPage = 25) {
        
        $query = "SELECT SQL_CALC_FOUND_ROWS u.user_id, u.username, CONCAT('/user/', u.user_id) AS url, i.*
            FROM image_flags AS f
            LEFT JOIN nuke_users AS u ON f.screened_by = u.user_id
            LEFT JOIN image AS i ON f.image_id = i.id
            WHERE f.rejected = 1
            ORDER BY f.screened_on DESC
            LIMIT ?, ?";
        
        $params = [
            ($page - 1) * $itemsPerPage, 
            $itemsPerPage
        ];
        
        $return = array(
            "total" => 0,
            "page" => $page,
            "items_per_page" => $itemsPerPage,
            "photos" => array()
        ); 
        
        foreach ($this->db->fetchAll($query, $params) as $row) {
            $row['meta'] = json_decode($row['meta'], true);
            $row['meta']['sizes'] = Images::normaliseSizes($row['meta']['sizes']);
            $return['photos'][] = $row;
        }
        
        $return['total'] = $this->db->fetchOne("SELECT FOUND_ROWS() AS total");
        
        return $return;
        
    }
    
    /**
     * Get skipped images
     * @since Version 3.10.0
     * @param int $page
     * @param int $itemsPerPage
     * @return array
     */
    
    public function getSkippedImages($page = 1, $itemsPerPage = 25) {
        
        $query = "SELECT SQL_CALC_FOUND_ROWS i.*
            FROM image_flags_skip AS f
            LEFT JOIN image AS i ON f.image_id = i.id
            GROUP BY f.image_id
            ORDER BY f.date DESC
            LIMIT ?, ?";
        
        $params = [
            ($page - 1) * $itemsPerPage, 
            $itemsPerPage
        ];
        
        $return = array(
            "total" => 0,
            "page" => $page,
            "items_per_page" => $itemsPerPage,
            "photos" => array()
        ); 
        
        foreach ($this->db->fetchAll($query, $params) as $row) {
            $row['meta'] = json_decode($row['meta'], true);
            $row['meta']['sizes'] = Images::normaliseSizes($row['meta']['sizes']);
            $return['photos'][] = $row;
        }
        
        $return['total'] = $this->db->fetchOne("SELECT FOUND_ROWS() AS total");
        
        return $return;
        
    }
    
    /**
     * Get the last review date by a given user
     * @since Version 3.10.0
     * @param \Railpage\Users\User $userObject
     * @return \DateTime|false Returns false if guest, or no review date found
     */
    
    public static function getLastReviewDate(User $userObject) {
        
        if (!filter_var($userObject->id, FILTER_VALIDATE_INT)) {
            return false;
        }
        
        $Database = AppCore::GetDatabase(); 
        
        $query = "SELECT screened_on FROM image_flags WHERE screened_by = ? ORDER BY screened_on DESC LIMIT 0, 1";
        
        $date = $Database->fetchOne($query, $userObject->id); 
        
        if (!$date) {
            
            $maintainers = [ 
                11437,
                13666
            ];
            
            if (in_array($userObject->id, $maintainers)) {
                return new DateTime("jan 1 1970"); 
            }
            
            return false;
        }
        
        return new DateTime($date); 
        
    }
    
    /**
     * Get screeners who haven't done any work in the last seven days
     * @since Version 3.10.0
     * @return array
     */
    
    public static function getLazyScreeners() {
        
        $Database = AppCore::GetDatabase(); 
        
        $query = "SELECT * FROM ( 
            SELECT u.user_id, u.username, u.user_email, MAX(s.screened_on) AS last_screen 
            FROM image_flags AS s 
            LEFT JOIN nuke_users AS u ON u.user_id = s.screened_by 
            GROUP BY u.user_id 
        ) AS screeners 
        WHERE user_id NOT IN (2) 
        AND last_screen < DATE_SUB(NOW(), INTERVAL 7 DAY)";
        
        return $Database->fetchAll($query); 
        
    }
    
}