Version 4.5.0

This commit is contained in:
Neo committed 2025-12-19 05:51:58 -08:00
1 parent 1a0c7fd3c2
commit f79dcf067a
3791 files changed
+248032 -76372

No files matched your search

+106 -64
View File
@@ -11,7 +11,7 @@
namespace IPS\Helpers;
/* To prevent PHP errors (extending class does not exist) revealing path */
if ( !defined( '\IPS\SUITE_UNIQUE_KEY' ) )
if ( !\defined( '\IPS\SUITE_UNIQUE_KEY' ) )
{
header( ( isset( $_SERVER['SERVER_PROTOCOL'] ) ? $_SERVER['SERVER_PROTOCOL'] : 'HTTP/1.0' ) . ' 403 Forbidden' );
exit;
@@ -78,7 +78,7 @@ class _Form
public $hiddenValues = array();
/**
* @brief Extra attributes for <form> tag
* @brief Extra attributes for `<form>` tag
*/
public $attributes = array();
@@ -89,7 +89,7 @@ class _Form
/**
* @brief If form has upload field, the maximum size (Needed to add enctype="multipart/form-data")
* @ntoe Only actually affects no-JS uploads, Plupload does it's own thing
* @note Only actually affects no-JS uploads, Plupload does it's own thing
*/
protected $uploadField = FALSE;
@@ -124,7 +124,7 @@ class _Form
* @param string $id Form ID
* @param string $submitLang Language string for submit button
* @param \IPS\Http\Url|NULL $action Action URL
* @param array $attributes Extra attributes for <form> tag
* @param array $attributes Extra attributes for `<form>` tag
* @return void
*/
public function __construct( $id='form', $submitLang='save', $action=NULL, $attributes=array() )
@@ -167,7 +167,10 @@ class _Form
/**
* Add Tab
*
* @param string $lang Language key
* @param string $lang Language key
* @param string|null $icon Icon to use
* @param string|null $blurbLang Language to use for the blurb
* @param string|null $css CSS class to use for the tab
* @return void
*/
public function addTab( $lang, $icon=NULL, $blurbLang=NULL, $css=NULL )
@@ -199,34 +202,42 @@ class _Form
/**
* Add Header
*
* @param string $lang Language key
* @param string $lang Language key
* @param string|NULL $after The key of element to insert after
* @param string|NULL $tab The tab to insert onto
* @return void
*/
public function addHeader( $lang )
public function addHeader( $lang, $after=NULL, $tab=NULL )
{
$this->elements[ $this->currentTab ][] = \IPS\Theme::i()->getTemplate( 'forms', 'core' )->header( $lang, "{$this->id}_header_{$lang}" );
/* Place the input into the correct position */
$this->_insert( \IPS\Theme::i()->getTemplate( 'forms', 'core' )->header( $lang, "{$this->id}_header_{$lang}" ), NULL, $tab, $after );
}
/**
* Add Seperator
*
* @param string|NULL $after The key of element to insert after
* @param string|NULL $tab The tab to insert onto
* @return void
*/
public function addSeparator()
public function addSeparator( $after=NULL, $tab=NULL )
{
$this->elements[ $this->currentTab ][] = \IPS\Theme::i()->getTemplate( 'forms', 'core', 'front' )->seperator();
/* Place the input into the correct position */
$this->_insert( \IPS\Theme::i()->getTemplate( 'forms', 'core', 'front' )->seperator(), NULL, $tab, $after );
}
/**
* Add Message Row
*
* @param string $lang Language key or formatted string to display
* @param string $css Custom CSS class(es) to apply
* @param bool $parse Set this to false if the language string passed is already formatted for display
* @param string $_id HTML ID
* @param string $lang Language key or formatted string to display
* @param string $css Custom CSS class(es) to apply
* @param bool $parse Set this to false if the language string passed is already formatted for display
* @param string $_id HTML ID
* @param string|NULL $after The key of element to insert after
* @param string|NULL $tab The tab to insert onto
* @return void
*/
public function addMessage( $lang, $css='', $parse=TRUE, $_id=NULL )
public function addMessage( $lang, $css='', $parse=TRUE, $_id=NULL, $after=NULL, $tab=NULL )
{
if ( !$_id )
{
@@ -237,18 +248,22 @@ class _Form
}
}
$this->elements[ $this->currentTab ][] = \IPS\Theme::i()->getTemplate( 'forms', 'core', 'global' )->message( $lang, $_id, $css, $parse );
/* Place the input into the correct position */
$this->_insert( \IPS\Theme::i()->getTemplate( 'forms', 'core', 'global' )->message( $lang, $_id, $css, $parse ), NULL, $tab, $after );
}
/**
* Add Html
*
* @param string $html HTML to add
* @param string $html HTML to add
* @param string|NULL $after The key of element to insert after
* @param string|NULL $tab The tab to insert onto
* @return void
*/
public function addHtml( $html )
public function addHtml( $html, $after=NULL, $tab=NULL )
{
$this->elements[ $this->currentTab ][] = $html;
/* Place the input into the correct position */
$this->_insert( $html, NULL, $tab, $after );
}
/**
@@ -267,13 +282,17 @@ class _Form
*
* @param mixed $name Name to identify matrix
* @param \IPS\Helpers\Form\Matrix $matrix The Matrix
* @param string|NULL $after The key of element to insert after
* @param string|NULL $tab The tab to insert onto
* @return void
*/
public function addMatrix( $name, $matrix )
public function addMatrix( $name, $matrix, $after=NULL, $tab=NULL )
{
$matrix->formId = $this->id;
$this->tabClasses[ $this->currentTab ] = 'ipsMatrix';
$this->elements[ $this->currentTab ][ $name ] = $matrix;
/* Place the input into the correct position */
$this->_insert( $matrix, $name, $tab, $after );
}
/**
@@ -294,47 +313,33 @@ class _Form
/**
* Add Dummy Row
*
* @param string $langKey Language key
* @param string $value Value
* @param string $desc Field description
* @param string $warning Field warning
* @param string $id Element ID
* @param string $langKey Language key
* @param string $value Value
* @param string $desc Field description
* @param string $warning Field warning
* @param string $id Element ID
* @param string|NULL $after The key of element to insert after
* @param string|NULL $tab The tab to insert onto
* @return void
*/
public function addDummy( $langKey, $value, $desc='', $warning='', $id='' )
public function addDummy( $langKey, $value, $desc='', $warning='', $id='', $after=NULL, $tab=NULL )
{
$this->elements[ $this->currentTab ][] = \IPS\Theme::i()->getTemplate( 'forms', 'core' )->row( \IPS\Member::loggedIn()->language()->addToStack( $langKey ), $value, $desc, $warning, FALSE, NULL, NULL, NULL, $id );
/* Place the input into the correct position */
$this->_insert( \IPS\Theme::i()->getTemplate( 'forms', 'core' )->row( \IPS\Member::loggedIn()->language()->addToStack( $langKey ), $value, $desc, $warning, FALSE, NULL, NULL, NULL, $id ), NULL, $tab, $after );
}
/**
* Add Input
*
* @param \IPS\Helpers\Form\FormAbstract $input Form element to add
* @param string|NULL $after The key of element to insert after
* @param string|NULL $tab The tab to insert onto
* @param string|NULL $after The key of element to insert after
* @param string|NULL $tab The tab to insert onto
* @return void
*/
public function add( $input, $after=NULL, $tab=NULL )
{
$tab = $tab ?: $this->currentTab;
if ( $after )
{
$elements = array();
foreach ( $this->elements[ $tab ] as $key => $element )
{
$elements[ $key ] = $element;
if ( $key === $after )
{
$elements[ $input->name ] = $input;
}
}
$this->elements[ $tab ] = $elements;
}
else
{
$this->elements[ $tab ][ $input->name ] = $input;
}
/* Place the input into the correct position */
$this->_insert( $input, $input->name, $tab, $after );
/* If it's a captcha field, we need to add a hidden value */
if ( $input instanceof Form\Captcha )
@@ -354,7 +359,7 @@ class _Form
$this->languageKeys[] = $input->name . '_desc';
$this->languageKeys[] = $input->name . '_warning';
if ( isset( $input->options['options'] ) and count( $input->options['options'] ) )
if ( isset( $input->options['options'] ) and \count( $input->options['options'] ) )
{
$this->languageKeys = array_merge( $this->languageKeys, array_map(
function ($v )
@@ -376,6 +381,42 @@ class _Form
}
}
}
/**
* Actually place the element in the correct position
*
* @param mixed $element Thing we are adding (could be a form input, message, etc.)
* @param string|NULL $elementKey The key of the element
* @param string|NULL $tab The tab to insert this thing into
* @param string|NULL $after The key of the element we want to insert this thing after
* @return void
*/
protected function _insert( $element, $elementKey=NULL, $tab=NULL, $after=NULL )
{
$tab = $tab ?: $this->currentTab;
if ( $after )
{
$elements = array();
foreach ( $this->elements[ $tab ] as $key => $_element )
{
$elements[ $key ] = $_element;
if ( $key === $after )
{
$elements[ $elementKey ] = $element;
}
}
$this->elements[ $tab ] = $elements;
}
elseif( $elementKey )
{
$this->elements[ $tab ][ $elementKey ] = $element;
}
else
{
$this->elements[ $tab ][] = $element;
}
}
/**
* Get HTML
@@ -385,7 +426,7 @@ class _Form
public function __toString()
{
/* Preload languages */
if ( count( $this->languageKeys ) and !( \IPS\Member::loggedIn()->language() instanceof \IPS\Lang\Setup\Lang ) )
if ( \count( $this->languageKeys ) and !( \IPS\Member::loggedIn()->language() instanceof \IPS\Lang\Setup\Lang ) )
{
try
{
@@ -408,7 +449,7 @@ class _Form
$html[ $tab ] .= \IPS\Theme::i()->getTemplate( 'forms', 'core' )->emptyRow( $element->nested(), $k );
continue;
}
if ( !is_string( $element ) and $element->error )
if ( !\is_string( $element ) and $element->error )
{
$errorTabs[] = $tab;
}
@@ -441,9 +482,9 @@ class _Form
*/
public function customTemplate( $template )
{
$args = func_get_args();
$args = \func_get_args();
if ( count( $args ) > 1 )
if ( \count( $args ) > 1 )
{
array_shift( $args );
}
@@ -453,7 +494,7 @@ class _Form
}
/* Preload languages */
if ( count( $this->languageKeys ) )
if ( \count( $this->languageKeys ) )
{
try
{
@@ -473,7 +514,7 @@ class _Form
$html[ $tab ] .= \IPS\Theme::i()->getTemplate( 'forms', 'core' )->emptyRow( $element->nested(), $k );
continue;
}
if ( !is_string( $element ) and $element->error )
if ( !\is_string( $element ) and $element->error )
{
$errorTabs[] = $tab;
}
@@ -481,7 +522,8 @@ class _Form
}
}
return call_user_func_array( $template, array_merge( $args, array( $this->id, $this->action, $this->elements, $this->hiddenValues, $this->actionButtons, $this->uploadField, $this->class, $this->attributes, $this->sidebar, $this, $errorTabs ) ) );
$templateArguments = array_merge( $args, array( $this->id, $this->action, $this->elements, $this->hiddenValues, $this->actionButtons, $this->uploadField, $this->class, $this->attributes, $this->sidebar, $this, $errorTabs ) );
return $template( ...$templateArguments );
}
/**
@@ -515,7 +557,7 @@ class _Form
$uploadCurrentFiles = array();
/* Did we submit the form? */
if( isset( \IPS\Request::i()->$name ) and \IPS\Request::i()->csrfKey === \IPS\Session::i()->csrfKey )
if( isset( \IPS\Request::i()->$name ) and \IPS\Login::compareHashes( (string) \IPS\Session::i()->csrfKey, (string) \IPS\Request::i()->csrfKey ) )
{
/* Work out which fields are being toggled by other fields */
$htmlIdsToIgnoreBecauseTheyAreHiddenByToggles = array();
@@ -561,7 +603,7 @@ class _Form
{
foreach ( $element->options['toggles'] as $toggleValue => $toggleHtmlIds )
{
$match = is_array( $element->value ) ? in_array( $toggleValue, $element->value ) : $toggleValue == $element->value;
$match = \is_array( $element->value ) ? \in_array( $toggleValue, $element->value ) : $toggleValue == $element->value;
if ( !$match )
{
$htmlIdsToIgnoreBecauseTheyAreHiddenByToggles = array_merge( $htmlIdsToIgnoreBecauseTheyAreHiddenByToggles, $toggleHtmlIds );
@@ -597,7 +639,7 @@ class _Form
/* If this is dependant on a toggle which isn't set, don't return a value so that it doesn't
trigger an error we cannot see */
if ( $element->htmlId and in_array( $element->htmlId, $htmlIdsToIgnore ) )
if ( $element->htmlId and \in_array( $element->htmlId, $htmlIdsToIgnore ) )
{
$values[ $_name ] = $stringValues ? $element::stringValue( $element->defaultValue ) : $element->defaultValue;
continue;
@@ -616,14 +658,14 @@ class _Form
if ( $element->options['retainDeleted'] )
{
$uploadRetainDeleted[] = $element->name;
if ( is_array( $element->value ) )
if ( \is_array( $element->value ) )
{
foreach( $element->value AS $value )
{
$uploadCurrentFiles[] = $value->originalFilename;
}
}
else
elseif( $element->value !== NULL )
{
$uploadCurrentFiles[] = $element->value->originalFilename;
}
@@ -685,13 +727,13 @@ class _Form
/* At this point we are about to return the values. Any uploaded files are now the responsibility of the controller, so release the hold on them */
foreach ( $uploadFieldNames as $name )
{
if ( !in_array( $name, $uploadRetainDeleted ) )
if ( !\in_array( $name, $uploadRetainDeleted ) )
{
\IPS\Db::i()->delete( 'core_files_temp', array( 'upload_key=?', md5( $name . session_id() ) ) );
}
else
{
/* If we're retaining deleted files, then remove any files that are actually are a part of the valye */
/* If we're retaining deleted files, then remove any files that are actually are a part of the value */
\IPS\Db::i()->delete( 'core_files_temp', array( "upload_key=? AND " . \IPS\Db::i()->in( 'filename', $uploadCurrentFiles ), md5( $name . session_id() ) ) );
}
}