Seditio Source
Root |
./othercms/ips_4.3.4/applications/core/extensions/core/Queue/RebuildAttachmentThumbnails.php
<?php
/**
 * @brief        Background Task: Rebuild Attachment Thumbnails
 * @author        <a href='https://www.invisioncommunity.com'>Invision Power Services, Inc.</a>
 * @copyright    (c) Invision Power Services, Inc.
 * @license        https://www.invisioncommunity.com/legal/standards/
 * @package        Invision Community
 * @since        24 Nov 2015
 */

namespace IPS\core\extensions\core\Queue;

/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
   
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
    exit;
}

/**
 * Background Task: Rebuilds thumbnails for attached images
 */
class _RebuildAttachmentThumbnails
{
   
/**
     * @brief Number of thumbnails to build per cycle
     */
   
public $perCycle    = 5;
   
   
/**
     * Parse data before queuing
     *
     * @param    array    $data
     * @return    array
     */
   
public function preQueueData( $data )
    {
        try
        {
           
$data['count']        = \IPS\Db::i()->select( 'MAX(attach_id)', 'core_attachments', array( 'attach_is_image=?', 1 ) )->first();
           
$data['realCount']    = \IPS\Db::i()->select( 'COUNT(*)', 'core_attachments', array( 'attach_is_image=?', 1 ) )->first();
        }
        catch( \
Exception $ex )
        {
            throw new \
OutOfRangeException;
        }
       
        if(
$data['count'] == 0 or $data['realCount'] == 0 )
        {
            return
null;
        }

       
$data['indexed']    = 0;

        return
$data;
    }

   
/**
     * Run Background Task
     *
     * @param    mixed                        $data    Data as it was passed to \IPS\Task::queue()
     * @param    int                            $offset    Offset
     * @return    int                            New offset
     * @throws    \IPS\Task\Queue\OutOfRangeException    Indicates offset doesn't exist and thus task is complete
     */
   
public function run( &$data, $offset )
    {
       
$last    = NULL;
       
        \
IPS\Log::debug( "Rebuilding attachment thumbnails with an offset of " . $offset, 'rebuildAttachmentThumbnails' );

       
$thumbDims    = \IPS\Settings::i()->attachment_image_size ? explode( 'x', \IPS\Settings::i()->attachment_image_size ) : array( 1000, 750 );

        foreach( \
IPS\Db::i()->select( '*', 'core_attachments', array( 'attach_id > ? AND attach_is_image=?', $offset, 1 ), 'attach_id ASC', array( 0, $this->perCycle ) ) as $attachment )
        {
           
/* Did the rebuild previously time out on this? If so we need to skip it and move along */
           
if( isset( \IPS\Data\Store::i()->currentAttachmentRebuild ) )
            {
               
/* If the last rebuild cycle timed out, currentAttachmentRebuild might be set and we might have already rebuilt this attachment (the attachment that caused the rebuild to fail might come after this).
                    If that is the case, we should skip rebuilding this attachment again. */
               
if( \IPS\Data\Store::i()->currentAttachmentRebuild > $attachment['attach_id'] )
                {
                   
$last = $attachment['attach_id'];
                    continue;
                }

               
/* If the last rebuild cycle failed and we have just retrieved the attachment we last attempted to rebuild, skip it and move along */
               
if( \IPS\Data\Store::i()->currentAttachmentRebuild == $attachment['attach_id'] )
                {
                    unset( \
IPS\Data\Store::i()->currentAttachmentRebuild );
                   
$last = $attachment['attach_id'];
                    continue;
                }
            }

           
/* Set the last attachment ID we rebuilt now */
           
$last    = $attachment['attach_id'];

           
/* Set a flag so we know which attachment we are attempting to rebuild - if it fails, we can skip it next time */
           
\IPS\Data\Store::i()->currentAttachmentRebuild = $last;

            try
            {
               
$file = \IPS\File::get( 'core_Attachment', $attachment['attach_location'] );

               
/* If there is no existing thumb location AND the existing dimensions are smaller than those needed for a thumbnail,
                    we don't need to build a thumbnail */
               
if( !$attachment['attach_thumb_location'] )
                {
                   
$thumbDims    = \IPS\Settings::i()->attachment_image_size ? explode( 'x', \IPS\Settings::i()->attachment_image_size ) : array( 1000, 750 );
                   
$dimensions    = $file->getImageDimensions();

                    if (
$dimensions[0] < $thumbDims[0] and $dimensions[1] < $thumbDims[1] )
                    {
                        continue;
                    }
                }

                if(
$attachment['attach_thumb_location'] )
                {
                   
$thumb = \IPS\File::get( 'core_Attachment', $attachment['attach_thumb_location'] );
                   
$file->thumbnailName        = $thumb->filename;
                   
$file->thumbnailContainer    = $thumb->container;
                }

                \
IPS\Db::i()->update( 'core_attachments', array(
                   
'attach_thumb_location'    => (string) $file->thumbnail( 'core_Attachment', $thumbDims[0], $thumbDims[1] ),
                ), array(
"attach_id=?", $attachment['attach_id'] ) );
            }
            catch( \
RuntimeException $e )
            {
                continue;
            }
            catch( \
InvalidArgumentException $e )
            {
                continue;
            }

           
$data['indexed']++;

           
/* Now we will reset the rebuild flag we previously set since it rebuilt and saved successfully */
           
unset( \IPS\Data\Store::i()->currentAttachmentRebuild );
        }

        if(
$last === NULL )
        {
            throw new \
IPS\Task\Queue\OutOfRangeException;
        }

        return
$last;
    }
   
   
/**
     * Get Progress
     *
     * @param    mixed                    $data    Data as it was passed to \IPS\Task::queue()
     * @param    int                        $offset    Offset
     * @return    array( 'text' => 'Doing something...', 'complete' => 50 )    Text explaining task and percentage complete
     * @throws    \OutOfRangeException    Indicates offset doesn't exist and thus task is complete
     */
   
public function getProgress( $data, $offset )
    {
        return array(
'text' => \IPS\Member::loggedIn()->language()->addToStack('rebuilding_attachments'), 'complete' => ( $data['realCount'] * $data['indexed'] ) > 0 ? round( 100 / $data['realCount'] * $data['indexed'], 2 ) : 100 );
    }    
}