Version 5.0.0 beta 1
This commit is contained in:
1 parent
25ddeb65d6
commit
15c7beabc5
6736 files changed
+627902
-497943
No files matched your search
+211
-177
@@ -11,45 +11,74 @@
|
||||
namespace IPS\Helpers\Form;
|
||||
|
||||
/* To prevent PHP errors (extending class does not exist) revealing path */
|
||||
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
|
||||
use DomainException;
|
||||
use Exception;
|
||||
use InvalidArgumentException;
|
||||
use IPS\Db;
|
||||
use IPS\File;
|
||||
use IPS\File\Exception as FileException;
|
||||
use IPS\Image;
|
||||
use IPS\Lang;
|
||||
use IPS\Log;
|
||||
use IPS\Login;
|
||||
use IPS\Member;
|
||||
use IPS\Output;
|
||||
use IPS\Output\Plugin\Filesize;
|
||||
use IPS\Platform\Bridge;
|
||||
use IPS\Request;
|
||||
use IPS\Settings;
|
||||
use IPS\Theme;
|
||||
use LogicException;
|
||||
use RuntimeException;
|
||||
use UnderflowException;
|
||||
use function count;
|
||||
use function defined;
|
||||
use function in_array;
|
||||
use function is_array;
|
||||
use function is_object;
|
||||
use function is_string;
|
||||
use const IPS\IN_DEV;
|
||||
|
||||
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
|
||||
{
|
||||
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
header( ( $_SERVER['SERVER_PROTOCOL'] ?? 'HTTP/1.0' ) . ' 403 Forbidden' );
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Upload class for Form Builder
|
||||
*/
|
||||
class _Upload extends FormAbstract
|
||||
class Upload extends FormAbstract
|
||||
{
|
||||
/**
|
||||
* @brief Default Options
|
||||
* @code
|
||||
$defaultOptions = array(
|
||||
'storageExtension' => 'Profile', // The file storage extension to use. This is required if postKey is NULL and temporary is FALSE.
|
||||
'storageContainer' => NULL, // The file storage container to use.
|
||||
'multiple' => TRUE, // Specifies if the field should allow multiple file uploads. Default is FALSE.
|
||||
'image' => array( 'maxWidth' => 100, 'maxHeight' => 100 ), // If the upload must be an image, can pass TRUE or an array with max width and height (in which case, image will be resized appropriately). Default is NULL. Max width/height cannot be used in conjunction with temporary uploads. If it can be, but doesn't have to an image, and you still want to specify max width and height, add an "optional" property set to true
|
||||
'checkImage' => TRUE, // If TRUE, will load uploaded images into the image processing engine to automatically reorient if needed
|
||||
'allowedFileTypes' => array( 'pdf', 'txt' ), // Allowed file extensions. NULL allows any. Default is NULL.
|
||||
'maxFileSize' => 100, // Maximum file size in megabytes. NULL is no limit. Default is NULL. Note that there *may* be server limitations regardless of this value which are calculated automatically.
|
||||
'totalMaxSize' => 100, // If this is a "multiple" upload field, the maximum storage space allowed in total in megabytes.
|
||||
'maxFiles' => NULL, // Maximum number of files that can be uploaded
|
||||
'postKey' => 'abc', // If provided, uploads will be treated as post attachments using the given post key
|
||||
'temporary' => TRUE, // If TRUE, the image will not be moved and the filename returned, rather than an \IPS\File object. This should ONLY be used for files which are genuinely
|
||||
temporary (e.g. importing skins, languages) as the file will be deleted after the script finished executing. Default is FALSE.
|
||||
'callback' => function() { ... }, // A callback function to run against submitted files
|
||||
'minimize' => TRUE, // Default is minimized. Pass FALSE to show the maximized field. Cannot be used in conjunction with temporary uploads
|
||||
'retainDeleted' => FALSE, // By default, if you specify a default value and the user deletes the files specified, the files will be physically deleted. This option overrides this behaviour.
|
||||
'template' => 'core.attachments.fileItem', // The javascript template key to use when rendering uploaded items. e.g. core.attachments.fileItem
|
||||
'obscure' => TRUE, // Controls if an md5 hash should be added to the filename. *Must* be TRUE unless the uploaded files are public to all users (like emoticons),
|
||||
'supportsDelete' => TRUE // Should the uploaded file be direct deletable from the upload field
|
||||
'allowStockPhotos' => FALSE // If Pixabay enhancement is enabled, this will allow users to select stock art from Pixabay to upload
|
||||
'canBeModerated' => TRUE // Set to TRUE if this uploader is capable of holding the submitted content for moderation
|
||||
);
|
||||
* @endcode
|
||||
*/
|
||||
protected $defaultOptions = array(
|
||||
/**
|
||||
* @brief Default Options
|
||||
* @code
|
||||
* $defaultOptions = array(
|
||||
* 'storageExtension' => 'Profile', // The file storage extension to use. This is required if postKey is NULL and temporary is FALSE.
|
||||
* 'storageContainer' => NULL, // The file storage container to use.
|
||||
* 'multiple' => TRUE, // Specifies if the field should allow multiple file uploads. Default is FALSE.
|
||||
* 'image' => array( 'maxWidth' => 100, 'maxHeight' => 100 ), // If the upload must be an image, can pass TRUE or an array with max width and height (in which case, image will be resized appropriately). Default is NULL. Max width/height cannot be used in conjunction with temporary uploads. If it can be, but doesn't have to an image, and you still want to specify max width and height, add an "optional" property set to true
|
||||
* 'checkImage' => TRUE, // If TRUE, will load uploaded images into the image processing engine to automatically reorient if needed
|
||||
* 'allowedFileTypes' => array( 'pdf', 'txt' ), // Allowed file extensions. NULL allows any. Default is NULL.
|
||||
* 'maxFileSize' => 100, // Maximum file size in megabytes. NULL is no limit. Default is NULL. Note that there *may* be server limitations regardless of this value which are calculated automatically.
|
||||
* 'totalMaxSize' => 100, // If this is a "multiple" upload field, the maximum storage space allowed in total in megabytes.
|
||||
* 'maxFiles' => NULL, // Maximum number of files that can be uploaded
|
||||
* 'postKey' => 'abc', // If provided, uploads will be treated as post attachments using the given post key
|
||||
* 'temporary' => TRUE, // If TRUE, the image will not be moved and the filename returned, rather than an \IPS\File object. This should ONLY be used for files which are genuinely
|
||||
* temporary (e.g. importing skins, languages) as the file will be deleted after the script finished executing. Default is FALSE.
|
||||
* 'callback' => function() { ... }, // A callback function to run against submitted files
|
||||
* 'minimize' => TRUE, // Default is minimized. Pass FALSE to show the maximized field. Cannot be used in conjunction with temporary uploads
|
||||
* 'retainDeleted' => FALSE, // By default, if you specify a default value and the user deletes the files specified, the files will be physically deleted. This option overrides this behaviour.
|
||||
* 'template' => 'core.attachments.fileItem', // The javascript template key to use when rendering uploaded items. e.g. core.attachments.fileItem
|
||||
* 'obscure' => TRUE, // Controls if an md5 hash should be added to the filename. *Must* be TRUE unless the uploaded files are public to all users (like emoticons),
|
||||
* 'supportsDelete' => TRUE // Should the uploaded file be direct deletable from the upload field
|
||||
* 'allowStockPhotos' => FALSE // If Pixabay enhancement is enabled, this will allow users to select stock art from Pixabay to upload
|
||||
* 'canBeModerated' => TRUE // Set to TRUE if this uploader is capable of holding the submitted content for moderation
|
||||
* );
|
||||
* @endcode
|
||||
*/
|
||||
protected array $defaultOptions = array(
|
||||
'multiple' => FALSE,
|
||||
'image' => NULL,
|
||||
'checkImage' => TRUE,
|
||||
@@ -75,29 +104,28 @@ class _Upload extends FormAbstract
|
||||
/**
|
||||
* @brief Max chunk size (in MB)
|
||||
*/
|
||||
protected $maxChunkSize;
|
||||
protected int|float $maxChunkSize;
|
||||
|
||||
/**
|
||||
* @brief Template
|
||||
*/
|
||||
public $template;
|
||||
|
||||
public array $template;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
* Sets that the max file size based on PHP's limits as well as the specified one
|
||||
*
|
||||
* @see \IPS\Helpers\Form\FormAbstract::__construct
|
||||
* @param string $name Name
|
||||
* @param mixed $defaultValue Default value
|
||||
* @param bool $required Required?
|
||||
* @param array $options Type-specific options
|
||||
* @param callback $customValidationCode Custom validation code
|
||||
* @param string $prefix HTML to show before input field
|
||||
* @param string $suffix HTML to show after input field
|
||||
* @param string $id The ID to add to the row
|
||||
* @return void
|
||||
* @param string $name Name
|
||||
* @param mixed $defaultValue Default value
|
||||
* @param bool $required Required?
|
||||
* @param array $options Type-specific options
|
||||
* @param callable|null $customValidationCode Custom validation code
|
||||
* @param string|null $prefix HTML to show before input field
|
||||
* @param string|null $suffix HTML to show after input field
|
||||
* @param string|null $id The ID to add to the row
|
||||
* @see FormAbstract::__construct
|
||||
*/
|
||||
public function __construct( $name, $defaultValue=NULL, $required=FALSE, $options=array(), $customValidationCode=NULL, $prefix=NULL, $suffix=NULL, $id=NULL )
|
||||
public function __construct( string $name, mixed $defaultValue=NULL, ?bool $required=FALSE, array $options=array(), callable $customValidationCode=NULL, string $prefix=NULL, string $suffix=NULL, string $id=NULL )
|
||||
{
|
||||
/* What's PHP's upload limit */
|
||||
if ( $maxChunkSize = static::maxChunkSize() )
|
||||
@@ -108,7 +136,7 @@ class _Upload extends FormAbstract
|
||||
/* Can we really use stock photos? */
|
||||
if ( ! empty( $options['allowStockPhotos'] ) )
|
||||
{
|
||||
if ( ! \IPS\Settings::i()->pixabay_enabled )
|
||||
if ( ! Settings::i()->pixabay_enabled )
|
||||
{
|
||||
$options['allowStockPhotos'] = FALSE;
|
||||
}
|
||||
@@ -121,13 +149,13 @@ class _Upload extends FormAbstract
|
||||
}
|
||||
if ( ( !isset( $options['storageExtension'] ) or !$options['storageExtension'] ) and ( !isset( $options['temporary'] ) or !$options['temporary'] ) )
|
||||
{
|
||||
throw new \InvalidArgumentException;
|
||||
throw new InvalidArgumentException;
|
||||
}
|
||||
|
||||
/* Does the storage extension support chunking? */
|
||||
if ( isset( $options['storageExtension'] ) and $options['storageExtension'] )
|
||||
{
|
||||
$storageClass = \IPS\File::getClass( $options['storageExtension'] );
|
||||
$storageClass = File::getClass( $options['storageExtension'] );
|
||||
|
||||
/* If the storage engine has a minimum chunk size, but our server can't handle uploads that large, we can't support chunking */
|
||||
$supportsChunking = $storageClass::$supportsChunking;
|
||||
@@ -146,7 +174,7 @@ class _Upload extends FormAbstract
|
||||
}
|
||||
}
|
||||
/* If we don't... */
|
||||
elseif ( !$supportsChunking )
|
||||
else
|
||||
{
|
||||
/* Then we need to set the maximum file size to what our server can handle */
|
||||
if ( !isset( $options['maxFileSize'] ) or $this->maxChunkSize < $options['maxFileSize'] )
|
||||
@@ -158,79 +186,83 @@ class _Upload extends FormAbstract
|
||||
|
||||
if( isset( $options['maxFileSize'] ) AND $options['maxFileSize'] <= 0 )
|
||||
{
|
||||
throw new \InvalidArgumentException;
|
||||
throw new InvalidArgumentException;
|
||||
}
|
||||
|
||||
if( isset( $options['maxFiles'] ) AND $options['maxFiles'] <= 0 )
|
||||
{
|
||||
throw new \InvalidArgumentException;
|
||||
throw new InvalidArgumentException;
|
||||
}
|
||||
|
||||
/* If this has to be an image, set the allowed file types */
|
||||
if ( isset( $options['image'] ) and !isset( $options['image']['optional'] ) and !isset( $options['allowedFileTypes'] ) )
|
||||
{
|
||||
$options['allowedFileTypes'] = \IPS\Image::supportedExtensions();
|
||||
$options['allowedFileTypes'] = Image::supportedExtensions();
|
||||
}
|
||||
|
||||
/* Call parent constructor */
|
||||
parent::__construct( $name, $defaultValue, $required, $options, $customValidationCode, $prefix, $suffix, $id );
|
||||
$processingAjax = isset( $_SERVER['HTTP_X_PLUPLOAD'] ) AND Login::compareHashes( $_SERVER['HTTP_X_PLUPLOAD'], md5( $this->name . session_id() ) );
|
||||
|
||||
/* Add JS */
|
||||
if ( \IPS\IN_DEV )
|
||||
if ( !$processingAjax )
|
||||
{
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'plupload/moxie.js', 'core', 'interface' ) );
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'plupload/plupload.dev.js', 'core', 'interface' ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->jsFiles = array_merge( \IPS\Output::i()->jsFiles, \IPS\Output::i()->js( 'plupload/plupload.full.min.js', 'core', 'interface' ) );
|
||||
if ( IN_DEV )
|
||||
{
|
||||
Output::i()->jsFiles = array_merge( Output::i()->jsFiles, Output::i()->js( 'plupload/moxie.js', 'core', 'interface' ) );
|
||||
Output::i()->jsFiles = array_merge( Output::i()->jsFiles, Output::i()->js( 'plupload/plupload.dev.js', 'core', 'interface' ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
Output::i()->jsFiles = array_merge( Output::i()->jsFiles, Output::i()->js( 'plupload/plupload.full.min.js', 'core', 'interface' ) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( \IPS\Settings::i()->ipb_url_filter_option != 'none' )
|
||||
if ( Settings::i()->ipb_url_filter_option != 'none' )
|
||||
{
|
||||
$links = \IPS\Settings::i()->ipb_url_filter_option == "black" ? \IPS\Settings::i()->ipb_url_blacklist : \IPS\Settings::i()->ipb_url_whitelist;
|
||||
$links = Settings::i()->ipb_url_filter_option == "black" ? Settings::i()->ipb_url_blacklist : Settings::i()->ipb_url_whitelist;
|
||||
|
||||
if( $links )
|
||||
{
|
||||
$linkValues = array();
|
||||
$linkValues = explode( "," , $links );
|
||||
|
||||
if( \IPS\Settings::i()->ipb_url_filter_option == 'white' )
|
||||
if( Settings::i()->ipb_url_filter_option == 'white' )
|
||||
{
|
||||
$listValues[] = "http://" . parse_url( \IPS\Settings::i()->base_url, PHP_URL_HOST ) . "/*";
|
||||
$listValues[] = "http://" . parse_url( Settings::i()->base_url, PHP_URL_HOST ) . "/*";
|
||||
}
|
||||
|
||||
if ( !empty( $linkValues ) )
|
||||
{
|
||||
\IPS\Output::i()->headJs = \IPS\Output::i()->headJs . "ips.setSetting( '" . \IPS\Settings::i()->ipb_url_filter_option . "list', " . json_encode( $linkValues ) . " );";
|
||||
Output::i()->headJs = Output::i()->headJs . "ips.setSetting( '" . Settings::i()->ipb_url_filter_option . "list', " . json_encode( $linkValues ) . " );";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Are we processing an AJAX upload? */
|
||||
if( isset( $_SERVER['HTTP_X_PLUPLOAD'] ) AND \IPS\Login::compareHashes( $_SERVER['HTTP_X_PLUPLOAD'], md5( $this->name . session_id() ) ) )
|
||||
if( isset( $_SERVER['HTTP_X_PLUPLOAD'] ) AND Login::compareHashes( $_SERVER['HTTP_X_PLUPLOAD'], md5( $this->name . session_id() ) ) )
|
||||
{
|
||||
try
|
||||
{
|
||||
/* Chunked */
|
||||
if ( $storageClass::$supportsChunking and method_exists( $storageClass, 'chunkInit' ) and isset( \IPS\Request::i()->chunks ) and \IPS\Request::i()->chunks > 1 )
|
||||
if ( $storageClass::$supportsChunking and method_exists( $storageClass, 'chunkInit' ) and isset( Request::i()->chunks ) and Request::i()->chunks > 1 )
|
||||
{
|
||||
/* If this is the FIRST chunk, start the process */
|
||||
if ( \IPS\Request::i()->chunk == 0 )
|
||||
if ( Request::i()->chunk == 0 )
|
||||
{
|
||||
$ref = $storageClass->chunkInit( \IPS\Request::i()->name, $this->options['storageContainer'], $this->options['obscure'] );
|
||||
$ref = $storageClass->chunkInit( Request::i()->name, $this->options['storageContainer'], $this->options['obscure'] );
|
||||
}
|
||||
else
|
||||
{
|
||||
$ref = $_SESSION['chunkUploads'][ md5( \IPS\Request::i()->name ) . '-' . $this->name ];
|
||||
$ref = $_SESSION['chunkUploads'][ md5( Request::i()->name ) . '-' . $this->name ];
|
||||
}
|
||||
|
||||
/* Process this chunk */
|
||||
$ref = $storageClass->chunkProcess( $ref, $_FILES[ $this->name ]['tmp_name'], \IPS\Request::i()->chunk );
|
||||
$_SESSION['chunkUploads'][ md5( \IPS\Request::i()->name ) . '-' . $this->name ] = $ref;
|
||||
$ref = $storageClass->chunkProcess( $ref, $_FILES[ $this->name ]['tmp_name'], Request::i()->chunk );
|
||||
$_SESSION['chunkUploads'][ md5( Request::i()->name ) . '-' . $this->name ] = $ref;
|
||||
|
||||
/* If this is the LAST chunk, finish the process */
|
||||
if ( \IPS\Request::i()->chunk == \IPS\Request::i()->chunks - 1 )
|
||||
if ( Request::i()->chunk == Request::i()->chunks - 1 )
|
||||
{
|
||||
$fileObj = $storageClass->chunkFinish( $ref, $this->options['storageExtension'] );
|
||||
|
||||
@@ -241,16 +273,16 @@ class _Upload extends FormAbstract
|
||||
'name' => $fileObj->originalFilename,
|
||||
'tmp_name' => $_FILES[ $this->name ]['tmp_name']
|
||||
);
|
||||
|
||||
|
||||
/* If there is an error, an exception will be thrown and will be caught below like normal */
|
||||
\IPS\File::validateUpload( $fileArray, $this->options['allowedFileTypes'], $this->options['maxFileSize'] );
|
||||
File::validateUpload( $fileArray, $this->options['allowedFileTypes'], $this->options['maxFileSize'] );
|
||||
|
||||
$exif = NULL;
|
||||
if ( $fileObj->isImage() )
|
||||
{
|
||||
try
|
||||
{
|
||||
$image = \IPS\Image::create( $fileObj->contents(), $this->options['checkImage'] ?: TRUE );
|
||||
$image = Image::create( $fileObj->contents(), $this->options['checkImage'] ?: TRUE );
|
||||
|
||||
if( $image::exifSupported() )
|
||||
{
|
||||
@@ -258,7 +290,10 @@ class _Upload extends FormAbstract
|
||||
$exif = $image->parseExif();
|
||||
}
|
||||
|
||||
$hasBeenResized = $image->resizeToMax( $this->options['image']['maxWidth'] ?? NULL, $this->options['image']['maxHeight'] ?? NULL );
|
||||
if( is_array( $this->options['image'] ) )
|
||||
{
|
||||
$hasBeenResized = $image->resizeToMax( $this->options['image']['maxWidth'] ?? NULL, $this->options['image']['maxHeight'] ?? NULL );
|
||||
}
|
||||
|
||||
/* If type JPG, image handler may strip meta data on image output */
|
||||
if( $hasBeenResized OR $image->hasBeenRotated OR $image->type == 'jpeg' )
|
||||
@@ -266,13 +301,13 @@ class _Upload extends FormAbstract
|
||||
$fileObj->replace( (string) $image );
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
catch ( Exception $e ) {}
|
||||
}
|
||||
|
||||
$insertId = \IPS\Db::i()->insert( 'core_files_temp', array(
|
||||
$insertId = Db::i()->insert( 'core_files_temp', array(
|
||||
'upload_key' => md5( $this->name . session_id() ),
|
||||
'filename' => $fileObj->originalFilename,
|
||||
'mime' => \IPS\File::getMimeType( $fileObj->originalFilename ),
|
||||
'mime' => File::getMimeType( $fileObj->originalFilename ),
|
||||
'contents' => (string) $fileObj,
|
||||
'time' => time(),
|
||||
'storage_extension' => $this->options['storageExtension'],
|
||||
@@ -289,18 +324,18 @@ class _Upload extends FormAbstract
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( array(
|
||||
Output::i()->json( array(
|
||||
'id' => $insertId,
|
||||
'key' => $_SERVER['HTTP_X_PLUPLOAD'],
|
||||
'imagesrc' => $fileObj->isImage() ? (string) $fileObj->url : NULL,
|
||||
'videosrc' => $fileObj->isVideo() ? (string) $fileObj->url : NULL,
|
||||
'thumbnail' => ( $fileObj->isImage() AND $fileObj->attachmentThumbnailUrl !== NULL and \is_string( $fileObj->attachmentThumbnailUrl ) ) ? \IPS\File::get( $this->options['storageExtension'], $fileObj->attachmentThumbnailUrl )->url : NULL,
|
||||
'thumbnail' => ( $fileObj->isImage() AND $fileObj->attachmentThumbnailUrl !== NULL and is_string( $fileObj->attachmentThumbnailUrl ) ) ? File::get( $this->options['storageExtension'], $fileObj->attachmentThumbnailUrl )->url : NULL,
|
||||
'securityKey' => $fileObj->securityKey
|
||||
) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Output::i()->json( array( 'chunk' => 'OK' ) );
|
||||
Output::i()->json( array( 'chunk' => 'OK' ) );
|
||||
}
|
||||
}
|
||||
/* Not chunked */
|
||||
@@ -308,58 +343,58 @@ class _Upload extends FormAbstract
|
||||
{
|
||||
foreach ( $this->processUploads() as $insertId => $fileObj )
|
||||
{
|
||||
\IPS\Output::i()->json( array(
|
||||
Output::i()->json( array(
|
||||
'id' => $insertId,
|
||||
'key' => $_SERVER['HTTP_X_PLUPLOAD'],
|
||||
'imagesrc' => $fileObj->isImage() ? (string) $fileObj->url : NULL,
|
||||
'videosrc' => $fileObj->isVideo() ? (string) $fileObj->url : NULL,
|
||||
'thumbnail' => ( $fileObj->isImage() AND $fileObj->attachmentThumbnailUrl !== NULL and \is_string( $fileObj->attachmentThumbnailUrl ) ) ? \IPS\File::get( $this->options['storageExtension'], $fileObj->attachmentThumbnailUrl )->url : NULL,
|
||||
'thumbnail' => ( $fileObj->isImage() AND $fileObj->attachmentThumbnailUrl !== NULL and is_string( $fileObj->attachmentThumbnailUrl ) ) ? File::get( $this->options['storageExtension'], $fileObj->attachmentThumbnailUrl )->url : NULL,
|
||||
'securityKey' => $fileObj->securityKey
|
||||
) );
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e )
|
||||
catch ( Exception $e )
|
||||
{
|
||||
\IPS\Log::debug( $e, 'upload_failure' );
|
||||
Log::debug( $e, 'upload_failure' );
|
||||
|
||||
$message = $e->getMessage();
|
||||
|
||||
if( $e instanceof \IPS\File\Exception )
|
||||
if( $e instanceof FileException )
|
||||
{
|
||||
$message = \IPS\Member::loggedIn()->language()->addToStack("files-{$e->getCode()}", FALSE, array( 'sprintf' => array( $e->originalFilename ?: $e->file ) ) );
|
||||
$message = Member::loggedIn()->language()->addToStack("files-{$e->getCode()}", FALSE, array( 'sprintf' => array( $e->originalFilename ?: $e->filepath ) ) );
|
||||
}
|
||||
|
||||
$subMessage = NULL;
|
||||
|
||||
if( $e instanceof \IPS\File\Exception AND $extra = $e->extraErrorMessage() )
|
||||
if( $e instanceof FileException AND $extra = $e->extraErrorMessage() )
|
||||
{
|
||||
if ( \IPS\Member::loggedIn()->isAdmin() and \IPS\Member::loggedIn()->language()->checkKeyExists( $extra . "_admin" ) )
|
||||
if ( Member::loggedIn()->isAdmin() and Member::loggedIn()->language()->checkKeyExists( $extra . "_admin" ) )
|
||||
{
|
||||
$subMessage = \IPS\Member::loggedIn()->language()->addToStack( $extra . "_admin" );
|
||||
$subMessage = Member::loggedIn()->language()->addToStack( $extra . "_admin" );
|
||||
}
|
||||
else
|
||||
{
|
||||
$subMessage = \IPS\Member::loggedIn()->language()->addToStack( $extra );
|
||||
$subMessage = Member::loggedIn()->language()->addToStack( $extra );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( \IPS\Member::loggedIn()->isAdmin() and \IPS\Member::loggedIn()->language()->checkKeyExists("uploaderr_{$e->getMessage()}_admin") )
|
||||
if ( Member::loggedIn()->isAdmin() and Member::loggedIn()->language()->checkKeyExists("uploaderr_{$e->getMessage()}_admin") )
|
||||
{
|
||||
$subMessage = \IPS\Member::loggedIn()->language()->addToStack( "uploaderr_{$e->getMessage()}_admin" );
|
||||
$subMessage = Member::loggedIn()->language()->addToStack( "uploaderr_{$e->getMessage()}_admin" );
|
||||
}
|
||||
elseif ( \IPS\Member::loggedIn()->language()->checkKeyExists("uploaderr_{$e->getMessage()}") )
|
||||
elseif ( Member::loggedIn()->language()->checkKeyExists("uploaderr_{$e->getMessage()}") )
|
||||
{
|
||||
$subMessage = \IPS\Member::loggedIn()->language()->addToStack( "uploaderr_{$e->getMessage()}" );
|
||||
$subMessage = Member::loggedIn()->language()->addToStack( "uploaderr_{$e->getMessage()}" );
|
||||
}
|
||||
else
|
||||
{
|
||||
$subMessage = \IPS\Member::loggedIn()->language()->addToStack("uploaderr_unspecified" );
|
||||
$subMessage = Member::loggedIn()->language()->addToStack("uploaderr_unspecified" );
|
||||
}
|
||||
}
|
||||
|
||||
\IPS\Output::i()->json( array(
|
||||
Output::i()->json( array(
|
||||
'error' => $message,
|
||||
'extra' => $e->getCode(),
|
||||
'sub' => $subMessage
|
||||
@@ -368,20 +403,20 @@ class _Upload extends FormAbstract
|
||||
}
|
||||
|
||||
/* Set the template */
|
||||
$this->template = array( \IPS\Theme::i()->getTemplate( 'forms', 'core', 'global' ), 'upload' );
|
||||
$this->template = array( Theme::i()->getTemplate( 'forms', 'core', 'global' ), 'upload' );
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Build the HTML once or we lose the custom properties sent
|
||||
*/
|
||||
protected $builtHtml = NULL;
|
||||
protected ?string $builtHtml = NULL;
|
||||
|
||||
/**
|
||||
* Get HTML without row template
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function html()
|
||||
public function html(): string
|
||||
{
|
||||
if( $this->builtHtml !== NULL )
|
||||
{
|
||||
@@ -393,7 +428,7 @@ class _Upload extends FormAbstract
|
||||
/* Put the value in an array if we need to */
|
||||
if ( $this->value !== NULL and ! empty( $this->value ) )
|
||||
{
|
||||
if ( $this->options['multiple'] !== TRUE and !\is_array( $this->value ) )
|
||||
if ( $this->options['multiple'] !== TRUE and !is_array( $this->value ) )
|
||||
{
|
||||
$this->value = array( $this->value );
|
||||
}
|
||||
@@ -402,12 +437,12 @@ class _Upload extends FormAbstract
|
||||
/* Build JSON version of the existing value, which allows the widget to build the interface */
|
||||
$existing = array();
|
||||
|
||||
if( $this->value and \count( $this->value ) )
|
||||
if( $this->value and count( $this->value ) )
|
||||
{
|
||||
foreach( $this->value as $id => $file )
|
||||
{
|
||||
/* If this was attachment data, expand */
|
||||
if( \is_array( $file ) )
|
||||
if( is_array( $file ) )
|
||||
{
|
||||
$attachment = $file;
|
||||
$file = $file['fileurl'];
|
||||
@@ -427,7 +462,7 @@ class _Upload extends FormAbstract
|
||||
'insertable' => (bool) $this->options['postKey'],
|
||||
'hasThumb' => false,
|
||||
'originalFileName' => $file,
|
||||
'size' => \IPS\Output\Plugin\Filesize::humanReadableFilesize( $file, FALSE, TRUE ),
|
||||
'size' => Filesize::humanReadableFilesize( $file, FALSE, TRUE ),
|
||||
'sizeRaw' => $file,
|
||||
'custom' => NULL
|
||||
);
|
||||
@@ -441,65 +476,58 @@ class _Upload extends FormAbstract
|
||||
'insertable' => (bool) $this->options['postKey'],
|
||||
'hasThumb' => ( isset( $attachment ) AND isset( $attachment['attach_is_image'] ) ) ? ( $attachment['attach_is_image'] AND $attachment['attach_thumb_location'] ) : $file->isImage(),
|
||||
'originalFileName' => $file->originalFilename,
|
||||
'thumbnail' => ( isset( $attachment ) AND isset( $attachment['attach_is_image'] ) AND $attachment['attach_is_image'] AND $attachment['attach_thumb_location'] ) ? ( (string) \IPS\File::get( $this->options['storageExtension'], $attachment['attach_thumb_location'] )->url ) : ( $file->isImage() ? (string) $file->url : NULL ),
|
||||
'size' => \IPS\Output\Plugin\Filesize::humanReadableFilesize( $file->filesize(), FALSE, TRUE ),
|
||||
'thumbnail' => ( isset( $attachment ) AND isset( $attachment['attach_is_image'] ) AND $attachment['attach_is_image'] AND $attachment['attach_thumb_location'] ) ? ( (string) File::get( $this->options['storageExtension'], $attachment['attach_thumb_location'] )->url ) : ( $file->isImage() ? (string) $file->url : NULL ),
|
||||
'size' => Filesize::humanReadableFilesize( $file->filesize(), FALSE, TRUE ),
|
||||
'sizeRaw' => $file->filesize(),
|
||||
'default' => ( isset( $attachment ) AND $attachment['default'] ) ? $attachment['default'] : NULL,
|
||||
);
|
||||
}
|
||||
catch( \UnderflowException $e ){}
|
||||
catch( UnderflowException $e ){}
|
||||
}
|
||||
}
|
||||
|
||||
foreach( $this->value as $id => $file )
|
||||
{
|
||||
$this->value[ $id ] = ( \is_array( $file ) ) ? $file['fileurl'] : $file;
|
||||
$this->value[ $id ] = ( is_array( $file ) ) ? $file['fileurl'] : $file;
|
||||
}
|
||||
}
|
||||
|
||||
/* We want this to use decimals even if locale wants commas for decimal separator, i.e. for uploader */
|
||||
$maxFileSize = $this->options['maxFileSize'] ? number_format( $this->options['maxFileSize'], 2, '.', '' ) : $this->options['maxFileSize'];
|
||||
|
||||
/* Do we have maximum image dimensions which we can ask plupload to handle for us client-side? */
|
||||
$maxImageDims = NULL;
|
||||
if ( $this->options['image'] and isset( $this->options['image']['maxWidth'] ) and isset( $this->options['image']['maxHeight'] ) )
|
||||
{
|
||||
$maxImageDims = "{$this->options['image']['maxWidth']}x{$this->options['image']['maxHeight']}";
|
||||
}
|
||||
|
||||
/* The html() method is called more than once, however $this->value is wiped out so if it was an attachments array all of the array properties are lost */
|
||||
$templateFunction = $this->template;
|
||||
$this->builtHtml = $templateFunction( $this->name, $this->value, $this->options['minimize'], $maxFileSize, $this->options['maxFiles'], $this->maxChunkSize, $this->options['totalMaxSize'], $this->options['allowedFileTypes'], $uploadKey, $this->options['multiple'], $this->options['postKey'], $this->options['temporary'] or ( \IPS\Lang::vleActive() ), $this->options['template'], $existing, $this->options['default'], $this->options['supportsDelete'], $maxImageDims, $this->options['allowStockPhotos'] );
|
||||
$this->builtHtml = $templateFunction( $this->name, $this->value, $this->options['minimize'], $maxFileSize, $this->options['maxFiles'], $this->maxChunkSize, $this->options['totalMaxSize'], $this->options['allowedFileTypes'], $uploadKey, $this->options['multiple'], $this->options['postKey'], $this->options['temporary'] or ( Lang::vleActive() ), $this->options['template'], $existing, $this->options['default'], $this->options['supportsDelete'], $this->options['allowStockPhotos'] );
|
||||
return $this->builtHtml;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Value
|
||||
*
|
||||
* @return \IPS\File|array|NULL
|
||||
* @throws \LogicException
|
||||
* @throws \DomainException
|
||||
* @throws \RuntimeException
|
||||
* @return File|array|NULL
|
||||
* @throws LogicException
|
||||
* @throws DomainException
|
||||
* @throws RuntimeException
|
||||
*/
|
||||
public function getValue()
|
||||
public function getValue(): mixed
|
||||
{
|
||||
/* Get the files we had already */
|
||||
$return = array();
|
||||
$tempFiles = iterator_to_array( \IPS\Db::i()->select( 'id,contents,filename,exif,requires_moderation,labels', 'core_files_temp', array( 'upload_key=?', md5( $this->name . session_id() ) ) )->setKeyField('id') );
|
||||
$tempFiles = iterator_to_array( Db::i()->select( 'id,contents,filename,exif,requires_moderation,labels', 'core_files_temp', array( 'upload_key=?', md5( $this->name . session_id() ) ) )->setKeyField('id') );
|
||||
if ( $this->options['storageExtension'] )
|
||||
{
|
||||
$existingName = $this->name . '_existing';
|
||||
$keepName = $this->name . '_keep';
|
||||
$keep = \IPS\Request::i()->$keepName;
|
||||
if ( isset( \IPS\Request::i()->$existingName ) and \is_array( \IPS\Request::i()->$existingName ) )
|
||||
$keep = Request::i()->$keepName;
|
||||
if ( isset( Request::i()->$existingName ) and is_array( Request::i()->$existingName ) )
|
||||
{
|
||||
foreach ( \IPS\Request::i()->$existingName as $id => $tempId )
|
||||
foreach ( Request::i()->$existingName as $id => $tempId )
|
||||
{
|
||||
if ( isset( $keep[ $id ] ) )
|
||||
{
|
||||
if ( $tempId and isset( $tempFiles[ $tempId ] ) )
|
||||
{
|
||||
$file = \IPS\File::get( $this->options['storageExtension'], $tempFiles[ $tempId ]['contents'] );
|
||||
$file = File::get( $this->options['storageExtension'], $tempFiles[ $tempId ]['contents'] );
|
||||
$file->tempId = $tempId;
|
||||
/* Reset the original filename to the real file name as $this->originalFilename is generated from the now AWS-safe $this->filename */
|
||||
$file->originalFilename = $tempFiles[ $tempId ]['filename'];
|
||||
@@ -527,13 +555,13 @@ class _Upload extends FormAbstract
|
||||
{
|
||||
if ( $tempId and isset( $tempFiles[ $tempId ] ) )
|
||||
{
|
||||
\IPS\Db::i()->delete( 'core_files_temp', array( 'id=?', $tempId ) );
|
||||
Db::i()->delete( 'core_files_temp', array( 'id=?', $tempId ) );
|
||||
|
||||
try
|
||||
{
|
||||
\IPS\File::get( $this->options['storageExtension'], $tempFiles[ $tempId ]['contents'] )->delete();
|
||||
File::get( $this->options['storageExtension'], $tempFiles[ $tempId ]['contents'] )->delete();
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
catch ( Exception $e ) { }
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -557,7 +585,7 @@ class _Upload extends FormAbstract
|
||||
{
|
||||
$this->defaultValue[ $id ]->delete();
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
catch ( Exception $e ) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -567,7 +595,7 @@ class _Upload extends FormAbstract
|
||||
{
|
||||
try
|
||||
{
|
||||
if ( \is_array( $this->defaultValue ) )
|
||||
if ( is_array( $this->defaultValue ) )
|
||||
{
|
||||
foreach( $this->defaultValue as $file )
|
||||
{
|
||||
@@ -591,7 +619,7 @@ class _Upload extends FormAbstract
|
||||
{
|
||||
/* Don't delete file if new file upload has same name */
|
||||
$okToDelete = TRUE;
|
||||
foreach( $tempFiles as $id => $tmpFile )
|
||||
foreach( $tempFiles as $index => $tmpFile )
|
||||
{
|
||||
if ( (string) $this->defaultValue == $tmpFile['contents'] )
|
||||
{
|
||||
@@ -605,7 +633,7 @@ class _Upload extends FormAbstract
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ) { }
|
||||
catch ( Exception $e ) { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -615,30 +643,30 @@ class _Upload extends FormAbstract
|
||||
}
|
||||
|
||||
/* Process files from noscript fallback - If this is just an AJAX validate, don't do anything so we still have the files when we actually submit */
|
||||
if ( !\IPS\Request::i()->ajaxValidate )
|
||||
if ( !Request::i()->ajaxValidate )
|
||||
{
|
||||
try
|
||||
{
|
||||
/* We used to use array_merge but this reindexes the array - we want to retain the keys */
|
||||
$return = $return + $this->processUploads( "{$this->name}_noscript" );
|
||||
}
|
||||
catch ( \DomainException $e )
|
||||
catch ( DomainException $e )
|
||||
{
|
||||
/* If there is no file and field is not required, then that's fine */
|
||||
if( $e->getCode() !== 1 or $this->required )
|
||||
{
|
||||
/* We have to format the message because there are variables to swap out. */
|
||||
if ( \IPS\Member::loggedIn()->language()->checkKeyExists( 'pluploaderr_' . $e->getMessage() ) )
|
||||
if ( Member::loggedIn()->language()->checkKeyExists( 'pluploaderr_' . $e->getMessage() ) )
|
||||
{
|
||||
$message = \IPS\Member::loggedIn()->language()->get( 'pluploaderr_' . $e->getMessage() );
|
||||
$message = Member::loggedIn()->language()->get( 'pluploaderr_' . $e->getMessage() );
|
||||
$message = str_replace( '{{max_file_size}}', $this->maxChunkSize, $message );
|
||||
if ( \is_array( $this->options['allowedFileTypes'] ) )
|
||||
if ( is_array( $this->options['allowedFileTypes'] ) )
|
||||
{
|
||||
$message = str_replace( '{{allowed_extensions}}', implode( ', ', $this->options['allowedFileTypes'] ), $message );
|
||||
}
|
||||
$message = str_replace( '{{server_error_code}}', $e->getCode(), $message );
|
||||
|
||||
throw new \DomainException( $message, $e->getCode() );
|
||||
throw new DomainException( $message, $e->getCode() );
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -646,9 +674,9 @@ class _Upload extends FormAbstract
|
||||
}
|
||||
}
|
||||
}
|
||||
catch ( \RuntimeException $e )
|
||||
catch ( RuntimeException $e )
|
||||
{
|
||||
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack('upload_error_generic', FALSE, array( 'sprintf' => array( $e->getMessage() ) ) ), $e->getCode() );
|
||||
throw new DomainException( Member::loggedIn()->language()->addToStack('upload_error_generic', FALSE, array( 'sprintf' => array( $e->getMessage() ) ) ), $e->getCode() );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -662,7 +690,7 @@ class _Upload extends FormAbstract
|
||||
}
|
||||
if ( $total > $this->options['totalMaxSize'] * 1048576 )
|
||||
{
|
||||
throw new \DomainException( \IPS\Member::loggedIn()->language()->addToStack('uploaderr_total_size', FALSE, array( 'sprintf' => array( \IPS\Output\Plugin\Filesize::humanReadableFilesize( $this->options['totalMaxSize'] * 1048576 ) ) ) ) );
|
||||
throw new DomainException( Member::loggedIn()->language()->addToStack('uploaderr_total_size', FALSE, array( 'sprintf' => array( Filesize::humanReadableFilesize( $this->options['totalMaxSize'] * 1048576 ) ) ) ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -671,7 +699,7 @@ class _Upload extends FormAbstract
|
||||
|
||||
foreach( $return as $k => $v )
|
||||
{
|
||||
$toReturn[ $k ] = ( \is_array( $v ) AND isset( $v['fileurl'] ) ) ? $v['fileurl'] : $v;
|
||||
$toReturn[ $k ] = ( is_array( $v ) AND isset( $v['fileurl'] ) ) ? $v['fileurl'] : $v;
|
||||
}
|
||||
|
||||
$return = $toReturn;
|
||||
@@ -688,29 +716,29 @@ class _Upload extends FormAbstract
|
||||
/**
|
||||
* Process Uploads
|
||||
*
|
||||
* @param string $fieldName The field name to look for
|
||||
* @param string|null $fieldName The field name to look for
|
||||
* @return array
|
||||
* @throws \DomainException
|
||||
* @throws DomainException
|
||||
*/
|
||||
protected function processUploads( $fieldName=NULL )
|
||||
protected function processUploads( string $fieldName=NULL ): array
|
||||
{
|
||||
$return = array();
|
||||
|
||||
/* Temporary - just process uploads and return paths */
|
||||
if ( $this->options['temporary'] )
|
||||
{
|
||||
foreach( \IPS\File::normalizeFilesArray( $fieldName ) as $file )
|
||||
foreach( File::normalizeFilesArray( $fieldName ) as $file )
|
||||
{
|
||||
\IPS\File::validateUpload( $file, $this->options['allowedFileTypes'], $this->options['maxFileSize'] );
|
||||
File::validateUpload( $file, $this->options['allowedFileTypes'], $this->options['maxFileSize'] );
|
||||
|
||||
$ext = mb_strtolower( mb_substr( $file['name'], ( mb_strrpos( $file['name'], '.' ) + 1 ) ) );
|
||||
|
||||
/* Don't allow "XSS" in images */
|
||||
if( \in_array( $ext, \IPS\File::$safeFileExtensions ) AND \in_array( $ext, \IPS\Image::supportedExtensions() ) )
|
||||
if( in_array( $ext, File::$safeFileExtensions ) AND in_array( $ext, Image::supportedExtensions() ) )
|
||||
{
|
||||
if( \IPS\File::checkXssInFile( file_get_contents( $file['tmp_name'] ) ) )
|
||||
if( File::checkXssInFile( file_get_contents( $file['tmp_name'] ) ) )
|
||||
{
|
||||
throw new \DomainException( "SECURITY_EXCEPTION_RAISED", 99 );
|
||||
throw new DomainException( "SECURITY_EXCEPTION_RAISED", 99 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -726,20 +754,24 @@ class _Upload extends FormAbstract
|
||||
$canBeModerated = $options['canBeModerated'];
|
||||
$exifData = array();
|
||||
|
||||
$fileObjects = \IPS\File::createFromUploads( $this->options['storageExtension'], $fieldName, $this->options['allowedFileTypes'], $this->options['maxFileSize'], $this->options['totalMaxSize'], 0, function( $contents, $filename, $i ) use ( $options, &$requiresModeration, $canBeModerated, &$exifData )
|
||||
$fileObjects = File::createFromUploads( $this->options['storageExtension'], $fieldName, $this->options['allowedFileTypes'], $this->options['maxFileSize'], $this->options['totalMaxSize'], 0, function( $contents, $filename, $i ) use ( $options, &$requiresModeration, $canBeModerated, &$exifData )
|
||||
{
|
||||
$ext = mb_strtolower( mb_substr( $filename, mb_strrpos( $filename, '.' ) + 1 ) );
|
||||
|
||||
/* Do image-specific stuff */
|
||||
if ( \in_array( $ext, \IPS\Image::supportedExtensions() ) )
|
||||
if ( in_array( $ext, Image::supportedExtensions() ) )
|
||||
{
|
||||
/* Resize */
|
||||
$image = NULL;
|
||||
$hasBeenResized = FALSE;
|
||||
|
||||
try
|
||||
{
|
||||
$image = \IPS\Image::create( $contents, $options['checkImage'] ?: TRUE );
|
||||
$hasBeenResized = $image->resizeToMax( $options['image']['maxWidth'] ?? NULL, $options['image']['maxHeight'] ?? NULL );
|
||||
$image = Image::create( $contents, $options['checkImage'] ?: TRUE );
|
||||
if( is_array( $options['image'] ) )
|
||||
{
|
||||
$hasBeenResized = $image->resizeToMax( $options['image']['maxWidth'] ?? NULL, $options['image']['maxHeight'] ?? NULL );
|
||||
}
|
||||
|
||||
/* If type JPG, image handler may strip meta data on image output */
|
||||
if( $hasBeenResized OR $image->hasBeenRotated OR $image->type == 'jpeg' )
|
||||
@@ -748,7 +780,7 @@ class _Upload extends FormAbstract
|
||||
$contents = (string) $image;
|
||||
}
|
||||
}
|
||||
catch ( \Exception $e ) {}
|
||||
catch ( Exception $e ) {}
|
||||
}
|
||||
|
||||
return $contents;
|
||||
@@ -758,7 +790,7 @@ class _Upload extends FormAbstract
|
||||
{
|
||||
$exif = NULL;
|
||||
|
||||
if( isset( $exifData[ $i ] ) AND $fileExifData = $exifData[ $i ] OR ( \IPS\Image::exifSupported() and $fileObj->isImage() and $fileExifData = $fileObj->exifData ) )
|
||||
if( isset( $exifData[ $i ] ) AND $fileExifData = $exifData[ $i ] OR ( Image::exifSupported() and $fileObj->isImage() and $fileExifData = $fileObj->exifData ) )
|
||||
{
|
||||
$exif = json_encode( $fileExifData );
|
||||
}
|
||||
@@ -766,14 +798,14 @@ class _Upload extends FormAbstract
|
||||
$data = $this->populateTempData( array(
|
||||
'upload_key' => md5( $this->name . session_id() ),
|
||||
'filename' => $fileObj->originalFilename,
|
||||
'mime' => \IPS\File::getMimeType( $fileObj->originalFilename ),
|
||||
'mime' => File::getMimeType( $fileObj->originalFilename ),
|
||||
'contents' => (string) $fileObj,
|
||||
'time' => time(),
|
||||
'storage_extension' => $this->options['storageExtension'],
|
||||
'exif' => $exif
|
||||
), $fileObj, $options );
|
||||
|
||||
$insertId = \IPS\Db::i()->insert( 'core_files_temp', $data );
|
||||
$insertId = Db::i()->insert( 'core_files_temp', $data );
|
||||
|
||||
if ( $this->options['callback'] )
|
||||
{
|
||||
@@ -796,45 +828,47 @@ class _Upload extends FormAbstract
|
||||
/**
|
||||
* Validate
|
||||
*
|
||||
* @throws \InvalidArgumentException
|
||||
* @throws InvalidArgumentException
|
||||
* @return TRUE
|
||||
*/
|
||||
public function validate()
|
||||
public function validate(): bool
|
||||
{
|
||||
parent::validate();
|
||||
|
||||
if ( $this->required and empty( $this->value ) and ( !\IPS\Request::i()->ajaxValidate or !$this->options['temporary'] ) )
|
||||
if ( $this->required and empty( $this->value ) and ( !Request::i()->ajaxValidate or !$this->options['temporary'] ) )
|
||||
{
|
||||
throw new \InvalidArgumentException('form_required');
|
||||
throw new InvalidArgumentException('form_required');
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish populating the data before its inserted
|
||||
*
|
||||
* @param array $data Array of data to change/add to
|
||||
* @param \IPS\File $fileObj File Object data
|
||||
* @param File $fileObj File Object data
|
||||
* @param array $options Field options
|
||||
* @return array
|
||||
*/
|
||||
protected function populateTempData( array $data, \IPS\File $fileObj, array $options ): array
|
||||
protected function populateTempData( array $data, File $fileObj, array $options ): array
|
||||
{
|
||||
return $data;
|
||||
return Bridge::i()->uploadPopulateTempData( $data, $fileObj, $options );
|
||||
}
|
||||
|
||||
/**
|
||||
* String Value
|
||||
*
|
||||
* @param mixed $value The value
|
||||
* @return string|null
|
||||
* @return string|int|null
|
||||
*/
|
||||
public static function stringValue( $value )
|
||||
public static function stringValue( mixed $value ): string|int|null
|
||||
{
|
||||
if ( \is_array( $value ) )
|
||||
if ( is_array( $value ) )
|
||||
{
|
||||
return implode( ',', array_map( function( $v )
|
||||
{
|
||||
if ( \is_object( $v ) )
|
||||
if ( is_object( $v ) )
|
||||
{
|
||||
return (string) $v->url;
|
||||
}
|
||||
@@ -849,7 +883,7 @@ class _Upload extends FormAbstract
|
||||
*
|
||||
* @return int|NULL
|
||||
*/
|
||||
public static function maxChunkSize()
|
||||
public static function maxChunkSize(): ?int
|
||||
{
|
||||
if ( $potentialValues = static::maxChunkSizeValues() )
|
||||
{
|
||||
@@ -861,22 +895,22 @@ class _Upload extends FormAbstract
|
||||
/**
|
||||
* Get the maximum chunk size (i.e. PHP's limit) in bytes
|
||||
*
|
||||
* @return int|NULL
|
||||
* @return int|array|NULL
|
||||
*/
|
||||
public static function maxChunkSizeValues()
|
||||
public static function maxChunkSizeValues(): int|array|null
|
||||
{
|
||||
$potentialValues = array();
|
||||
if( (float) ini_get('upload_max_filesize') > 0 )
|
||||
{
|
||||
$potentialValues['upload_max_filesize'] = \IPS\File::returnBytes( ini_get('upload_max_filesize') );
|
||||
$potentialValues['upload_max_filesize'] = File::returnBytes( ini_get('upload_max_filesize') );
|
||||
}
|
||||
if( (float) ini_get('post_max_size') > 0 )
|
||||
{
|
||||
$potentialValues['post_max_size'] = \IPS\File::returnBytes( ini_get('post_max_size') ) - 1048576;
|
||||
$potentialValues['post_max_size'] = File::returnBytes( ini_get('post_max_size') ) - 1048576;
|
||||
}
|
||||
if( (float) ini_get('memory_limit') > 0 )
|
||||
{
|
||||
$potentialValues['memory_limit'] = \IPS\File::returnBytes( ini_get('memory_limit') );
|
||||
$potentialValues['memory_limit'] = File::returnBytes( ini_get('memory_limit') );
|
||||
}
|
||||
return $potentialValues;
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user