Seditio Source
Root |
./othercms/ips_4.3.4/applications/downloads/setup/upg_40000/upgrade.php
<?php
/**
 * @brief        4.0.0 Upgrade Code
 * @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
 * @subpackage    Downloads
 * @since        19 Nov 2013
 */

namespace IPS\downloads\setup\upg_40000;

/* 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;
}

/**
 * 4.0.0 Upgrade Code
 */
class _Upgrade
{
   
/**
     * Upgrade categories
     *
     * @return    array    If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
     */
   
public function step1()
    {
       
$perCycle    = 100;
       
$did        = 0;
       
$limit        = intval( \IPS\Request::i()->extra );
       
       
/* Try to prevent timeouts to the extent possible */
       
$cutOff        = \IPS\core\Setup\Upgrade::determineCutoff();
       
        foreach( \
IPS\Db::i()->select( '*', 'downloads_categories', null, 'downloads_categories.cid ASC', array( $limit, $perCycle ) )->join( 'core_permission_index', array( 'app=? and perm_type=? and perm_type_id=downloads_categories.cid', 'downloads', 'cat' ) ) as $category )
        {
            if (
$cutOff !== NULL AND time() >= $cutOff )
            {
                return (
$limit + $did );
            }
           
           
$did++;
           
           
$options    = unserialize( $category['coptions'] );
           
/* We make a guess as to whether approval should be required since it is no longer per-permission mask */
           
$approval    = ( !$category['perm_7'] or $category['perm_7'] == ',4,' ) ? 1 : 0;
           
$cid        = $category['cid'];
           
$name        = $category['cname'];
           
$desc        = $category['cdesc'];

           
$category    = \IPS\downloads\Category::constructFromData( $category );

           
$category->bitoptions['allowss']                = ( isset( $options['opt_allowss'] ) ) ? $options['opt_allowss'] : 0;
           
$category->bitoptions['reqss']                    = ( isset( $options['opt_reqss'] ) ) ? $options['opt_reqss'] : 0;
           
$category->bitoptions['comments']                = ( isset( $options['opt_comments'] ) ) ? $options['opt_comments'] : 0;
           
$category->bitoptions['moderation']                = $approval;
           
$category->bitoptions['comment_moderation']        = \IPS\Settings::i()->idm_comment_approval;
           
$category->bitoptions['moderation_edits']        = !\IPS\Settings::i()->idm_allow_autoedit;
           
$category->bitoptions['submitter_log']            = \IPS\Settings::i()->submitter_view_dl;
           
$category->bitoptions['reviews_download']        = \IPS\Settings::i()->must_dl_rate;
           
$category->bitoptions['topic_delete']            = ( isset( $options['opt_topicd'] ) ) ? $options['opt_topicd'] : 0;
           
$category->bitoptions['topic_screenshot']        = ( isset( $options['opt_topicss'] ) ) ? $options['opt_topicss'] : 0;

            \
IPS\Lang::saveCustom( 'downloads', "downloads_category_{$cid}", trim( $name ) );
            \
IPS\Lang::saveCustom( 'downloads', "downloads_category_{$cid}_npv", $options['opt_noperm_view'] ? \IPS\Text\Parser::parseStatic( $options['opt_noperm_view'], TRUE, NULL, NULL, TRUE, TRUE, TRUE ) : '' );
            \
IPS\Lang::saveCustom( 'downloads', "downloads_category_{$cid}_npd", $options['opt_noperm_dl'] ? \IPS\Text\Parser::parseStatic( $options['opt_noperm_dl'], TRUE, NULL, NULL, TRUE, TRUE, TRUE ) : '' );
            \
IPS\Lang::saveCustom( 'downloads', "downloads_category_{$cid}_desc", \IPS\Text\Parser::parseStatic( $desc, TRUE, NULL, NULL, TRUE, TRUE, TRUE ) );

           
$category->types            = '';
           
$category->sortorder        = 'file_' . \str_ireplace( array( ' DESC', ' ASC' ), '', $options['opt_sortorder'] );
           
$category->maxfile            = $options['opt_maxfile'] ?: null;
           
$category->maxss            = $options['opt_maxss'] ?: null;
           
$category->maxdims            = NULL; // We purposefully don't retain the `opt_thumb_x` setting, since that is intended for thumbnails only.
           
$category->versioning        = \IPS\Settings::i()->idm_versioning ? NULL : 0;
           
$category->log                = \IPS\Settings::i()->idm_logalldownloads ? ( \IPS\Settings::i()->idm_log_prune ?: NULL ) : 0;
           
$category->forum_id            = ( isset( $options['opt_topicf'] ) ) ? $options['opt_topicf'] : 0;
           
$category->topic_prefix        = ( isset( $options['opt_topicp'] ) ) ? $options['opt_topicp'] : 0;
           
$category->topic_suffix        = ( isset( $options['opt_topics'] ) ) ? $options['opt_topics'] : 0;

            try
            {
               
$latestFile    = \IPS\Db::i()->select( '*', 'downloads_files', array( 'file_open=? and file_cat=?', 1, $cid ), 'file_submitted DESC', array( 0, 1 ) )->first();

               
$category->last_file_id        = $latestFile['file_id'];
               
$category->last_file_date    = $latestFile['file_submitted'];
            }
            catch( \
UnderflowException $e )
            {
               
$category->last_file_id        = 0;
               
$category->last_file_date    = 0;
            }

           
$category->save();
        }
       
        if (
$did )
        {
            return (
$limit + $did );
        }
        else
        {
            \
IPS\Db::i()->update( 'core_permission_index', array( 'perm_type' => 'category' ), array( 'app=?', 'downloads' ) );
            \
IPS\Db::i()->dropColumn( 'downloads_categories', array( 'coptions', 'cname' ) );
           
            unset(
$_SESSION['_step1Count_40000_downloads'] );
           
            return
true;
        }
    }

   
/**
     * Custom title for this step
     *
     * @return string
     */
   
public function step1CustomTitle()
    {
       
$limit = isset( \IPS\Request::i()->extra ) ? \IPS\Request::i()->extra : 0;
       
        if ( !isset(
$_SESSION['_step1Count_40000_downloads'] ) )
        {
           
$_SESSION['_step1Count_40000_downloads'] = \IPS\Db::i()->select( 'COUNT(*)', 'downloads_categories' )->first();
        }
       
        return
"Upgrading download manager categories (Upgraded so far: " . ( ( $limit > $_SESSION['_step1Count_40000_downloads'] ) ? $_SESSION['_step1Count_40000_downloads'] : $limit ) . ' out of ' . $_SESSION['_step1Count_40000_downloads'] . ")";
    }

   
/**
     * Custom field translations
     *
     * @return    array    If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
     */
   
public function step2()
    {
        foreach( \
IPS\Db::i()->select( '*', 'downloads_cfields' ) as $field )
        {
            \
IPS\Lang::saveCustom( 'core', "downloads_field_{$field['cf_id']}", $field['cf_title'] );
            \
IPS\Lang::saveCustom( 'core', "downloads_field_{$field['cf_id']}_desc", $field['cf_desc'] );

           
$update    = array();

            switch(
$field['cf_type'] )
            {
                case
'input':
                   
$update['cf_type']    = 'Text';
                break;

                case
'textarea':
                   
$update['cf_type']    = 'TextArea';
                break;

                case
'drop':
                   
$update['cf_type']    = 'Select';
                break;

                case
'radio':
                   
$update['cf_type']    = 'Radio';
                break;

                case
'cbox':
                   
$update['cf_type']        = 'Select';
                   
$update['cf_multiple']    = TRUE;
                break;

                default:
                   
$update['cf_type']    = 'Text';
                break;
            }

            if(
$field['cf_type'] === 'Textarea' )
            {
               
$update['cf_type']    = 'TextArea';
            }
           
           
/* Fix custom input format */
           
if ( $field['cf_input_format'] )
            {
               
$regex = '/' . preg_quote( $field['cf_input_format'] ) . '/';
               
$regex = str_replace( 'n', '\d', $regex );
               
$regex = str_replace( 'a', '\w', $regex );
               
               
$update['cf_input_format'] = $regex;
            }
           
           
/* Fix the options */
           
if( $field['cf_content'] )
            {
               
$options    = explode( '|', $field['cf_content'] );
               
$newOptions    = array();

                foreach(
$options as $option )
                {
                    list(
$k, $v )    = explode( '=', $option );
                   
$newOptions[]    = $v;
                }

                if( !isset(
$_SESSION['pfieldsd'] ) )
                {
                   
$_SESSION['pfieldsd']    = array();
                }

               
$_SESSION['pfieldsd'][ $field['cf_id'] ]    = $field['cf_id'];
               
$update['cf_content']    = json_encode( $newOptions );
            }

            if(
count( $update ) )
            {
                \
IPS\Db::i()->update( 'downloads_cfields', $update, 'cf_id=' . $field['cf_id'] );
            }

           
/* Indexes are needed, otherwise you get an error if you try to edit the custom field later */
           
\IPS\Db::i()->addIndex( 'downloads_ccontent', array( 'name' => 'field_' . $field['cf_id'], 'type' => 'key', 'columns' => array( 'field_' . $field['cf_id'] ), 'length' => array( 255 ) ) );
        }

        \
IPS\Db::i()->dropColumn( 'downloads_cfields', array( 'cf_title', 'cf_desc' ) );

        return
TRUE;
    }

   
/**
     * Custom title for this step
     *
     * @return string
     */
   
public function step2CustomTitle()
    {
        return
"Upgrading download manager custom fields";
    }

   
/**
     * Fix watermark path
     *
     * @return    array    If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
     */
   
public function step3()
    {
        if( !isset(
$_SESSION['pfieldsd'] ) )
        {
            return
true;
        }

       
$update    = array();

        foreach(
$_SESSION['pfieldsd'] as $fieldId )
        {
           
$update[]    = "field_{$fieldId}=TRIM( BOTH ',' FROM field_{$fieldId} )";
        }

        if(
count( $update ) )
        {
            \
IPS\Db::i()->update( 'downloads_ccontent', implode( ", ", $update ) );
        }

        unset(
$_SESSION['pfieldsd'] );

        return
TRUE;
    }

   
/**
     * Custom title for this step
     *
     * @return string
     */
   
public function step3CustomTitle()
    {
        if( !isset(
$_SESSION['pfieldsd'] ) )
        {
            return
"No custom field data needs to be updated";
        }

        return
"Updating custom file fields";
    }

   
/**
     * Fix watermark path
     *
     * @return    array    If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
     */
   
public function step4()
    {
       
$setting = \IPS\Db::i()->select( '*', 'core_sys_conf_settings', "conf_key='idm_watermarkpath'" )->first();

        if(
$setting['conf_value'] )
        {
           
$pathBits    = explode( '/', $setting['conf_value'] );
           
$fileName    = array_pop( $pathBits );

            try
            {
               
$url = \IPS\File::create( 'downloads_Screenshots', $fileName, file_get_contents( $setting['conf_value'] ), NULL, TRUE, NULL, FALSE );

                \
IPS\Settings::i()->changeValues( array( 'idm_watermarkpath' => $url ) );
            }
            catch( \
Exception $e )
            {
                \
IPS\Settings::i()->changeValues( array( 'idm_watermarkpath' => '' ) );
            }
        }

        \
IPS\Db::i()->delete( 'core_sys_conf_settings', "conf_key IN ( 'idm_screenshot_url', 'idm_filestorage', 'idm_localfilepath', 'idm_localsspath', 'idm_remoteport', 'idm_remotessurl',
            'idm_remotefileurl', 'idm_filestorage', 'idm_remoteurl', 'idm_remoteuser', 'idm_remotepass', 'idm_remotesspath', 'idm_remotefilepath' )"
);

        return
TRUE;
    }

   
/**
     * Custom title for this step
     *
     * @return string
     */
   
public function step4CustomTitle()
    {
        return
"Fixing watermark configuration";
    }

   
/**
     * Set a default primary screenshot for each file
     *
     * @return    array    If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
     */
   
public function step5()
    {
       
$perCycle    = 500;
       
$did        = 0;
       
$limit        = intval( \IPS\Request::i()->extra );
       
       
/* Try to prevent timeouts to the extent possible */
       
$cutOff        = \IPS\core\Setup\Upgrade::determineCutoff();
       
        foreach( \
IPS\Db::i()->select( '*', 'downloads_files', null, 'file_id ASC', array( $limit, $perCycle ) ) as $file )
        {
            if (
$cutOff !== NULL AND time() >= $cutOff )
            {
                return (
$limit + $did );
            }
           
           
$did++;
           
           
/* Try to get the default screenshot if one is set */
           
try
            {
               
$defaultScreenshot = \IPS\Db::i()->select( 'record_id', 'downloads_files_records', array( "record_file_id=? AND record_type IN('sslink','ssupload') AND record_default=?", $file['file_id'], 1 ) )->first();

                \
IPS\Db::i()->update( 'downloads_files', array( 'file_primary_screenshot' => $defaultScreenshot ), array( 'file_id=?', $file['file_id'] ) );
            }
            catch( \
UnderflowException $e )
            {
               
/* Get the first screenshot for the file and set the primary screenshot flag */
               
try
                {
                   
$firstScreenshot = \IPS\Db::i()->select( 'record_id', 'downloads_files_records', array( "record_file_id=? AND record_type IN('sslink','ssupload')", $file['file_id'] ), 'record_id ASC', array( 0, 1 ) )->first();

                    \
IPS\Db::i()->update( 'downloads_files', array( 'file_primary_screenshot' => $firstScreenshot ), array( 'file_id=?', $file['file_id'] ) );
                }
                catch( \
UnderflowException $e )
                {
                    continue;
                }
            }
        }
       
        if (
$did )
        {
            return (
$limit + $did );
        }
        else
        {
            unset(
$_SESSION['_step5Count_40000_downloads'] );
           
            return
true;
        }
    }

   
/**
     * Custom title for this step
     *
     * @return string
     */
   
public function step5CustomTitle()
    {
       
$limit = isset( \IPS\Request::i()->extra ) ? \IPS\Request::i()->extra : 0;
       
        if ( !isset(
$_SESSION['_step5Count_40000_downloads'] ) )
        {
           
$_SESSION['_step5Count_40000_downloads'] = \IPS\Db::i()->select( 'COUNT(*)', 'downloads_files' )->first();
        }
       
        return
"Updating default screenshots (Updated so far: " . ( ( $limit > $_SESSION['_step5Count_40000_downloads'] ) ? $_SESSION['_step5Count_40000_downloads'] : $limit ) . ' out of ' . $_SESSION['_step5Count_40000_downloads'] . ")";
    }

   
/**
     * Fixing database-storage files
     *
     * @return    mixed    If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
     */
   
public function step6()
    {
       
/* The only files in core_files at this point would be from Downloads database file storage */
       
if( \IPS\Db::i()->select( 'COUNT(*)', 'core_files' )->first() )
        {
           
$offset = isset( \IPS\Request::i()->extra ) ? \IPS\Request::i()->extra : 0;
           
$select = \IPS\Db::i()->select( '*', 'core_files', NULL, 'id', array( $offset, 25 ) );
            if (
count( $select ) )
            {
                foreach (
$select as $row )
                {
                   
/* The MySQL FROM_BASE64() function uses a slightly different ruleset than PHP, so we have to do this in PHP */
                   
\IPS\Db::i()->update( 'core_files', array( 'contents' => base64_decode( $row['contents'] ) ), array( 'id=?', $row['id'] ) );
                }

                return
$offset + 25;
            }
            else
            {
                unset(
$_SESSION['_step6Count'] );
                return
TRUE;
            }
        }

        return
TRUE;
    }

   
/**
     * Custom title for this step
     *
     * @return string
     */
   
public function step6CustomTitle()
    {
       
/* Do we even have any to convert? */
       
if( !\IPS\Db::i()->select( 'COUNT(*)', 'core_files' )->first() )
        {
            return
NULL;
        }

       
$limit = isset( \IPS\Request::i()->extra ) ? \IPS\Request::i()->extra : 0;

        if( !isset(
$_SESSION['_step6Count'] ) )
        {
           
$_SESSION['_step6Count'] = \IPS\Db::i()->select( 'COUNT(*)', 'core_files' )->first();
        }

        return
"Updating database-stored files (Upgraded so far: " . ( ( $limit > $_SESSION['_step6Count'] ) ? $_SESSION['_step6Count'] : $limit ) . ' out of ' . $_SESSION['_step6Count'] . ')';
    }
   
   
/**
     * Finish - This is run after all apps have been upgraded
     *
     * @return    mixed    If returns TRUE, upgrader will proceed to next step. If it returns any other value, it will set this as the value of the 'extra' GET parameter and rerun this step (useful for loops)
     * @note    We opted not to let users run this immediately during the upgrade because of potential issues (it taking a long time and users stopping it or getting frustrated) but we can revisit later
     */
   
public function finish()
    {
       \
IPS\Task::queue( 'core', 'RebuildPosts', array( 'class' => 'IPS\downloads\File' ), 2 );
       \
IPS\Task::queue( 'core', 'RebuildPosts', array( 'class' => 'IPS\downloads\File\Comment' ), 2 );
       \
IPS\Task::queue( 'core', 'RebuildPosts', array( 'class' => 'IPS\downloads\File\Review' ), 2 );
       \
IPS\Task::queue( 'core', 'RebuildNonContentPosts', array( 'extension' => 'downloads_Categories' ), 2 );

        return
TRUE;
    }
}