Version 4.1.19
This commit is contained in:
1 parent
28bd025b35
commit
2bd5025018
2674 files changed
+233518
-77766
No files matched your search
@@ -2,9 +2,9 @@
|
||||
/**
|
||||
* @brief Custom Field Node
|
||||
* @author <a href='http://www.invisionpower.com'>Invision Power Services, Inc.</a>
|
||||
* @copyright (c) 2001 - SVN_YYYY Invision Power Services, Inc.
|
||||
* @copyright (c) 2001 - 2016 Invision Power Services, Inc.
|
||||
* @license http://www.invisionpower.com/legal/standards/
|
||||
* @package IPS Social Suite
|
||||
* @package IPS Community Suite
|
||||
* @since 11 Apr 2013
|
||||
* @version SVN_VERSION_NUMBER
|
||||
*/
|
||||
@@ -74,6 +74,11 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
{
|
||||
$key = static::$databaseColumnMap[ $key ];
|
||||
}
|
||||
|
||||
if( $value instanceof \IPS\Node\Model )
|
||||
{
|
||||
$value = $value->_id;
|
||||
}
|
||||
|
||||
return parent::__set( $key, $value );
|
||||
}
|
||||
@@ -120,25 +125,25 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
), static::$additionalFieldTypes );
|
||||
|
||||
$toggles = array(
|
||||
'CheckboxSet' => array( 'pf_content', 'pf_not_null' ),
|
||||
'Codemirror' => array( 'pf_not_null', 'pf_max_input' ),
|
||||
'Email' => array( 'pf_not_null', 'pf_max_input', 'pf_input_format', 'pf_search_type' ),
|
||||
'Member' => array( 'pf_not_null', 'pf_multiple' ),
|
||||
'Password' => array( 'pf_not_null', 'pf_max_input', 'pf_input_format', 'pf_search_type' ),
|
||||
'Select' => array( 'pf_not_null', 'pf_content', 'pf_multiple' ),
|
||||
'Tel' => array( 'pf_not_null', 'pf_max_input', 'pf_input_format', 'pf_search_type' ),
|
||||
'Text' => array( 'pf_not_null', 'pf_max_input', 'pf_input_format', 'pf_search_type' ),
|
||||
'TextArea' => array( 'pf_not_null', 'pf_max_input', 'pf_input_format', 'pf_search_type' ),
|
||||
'Url' => array( 'pf_not_null', 'pf_max_input', 'pf_input_format', 'pf_search_type' ),
|
||||
'Radio' => array( 'pf_content' ),
|
||||
'Address' => array( 'pf_not_null'),
|
||||
'Color' => array( 'pf_not_null' ),
|
||||
'Date' => array( 'pf_not_null' ),
|
||||
'Editor' => array( 'pf_not_null' ),
|
||||
'Number' => array( 'pf_not_null' ),
|
||||
'CheckboxSet' => array( 'pf_content', 'pf_not_null', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'Codemirror' => array( 'pf_not_null', 'pf_max_input', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'Email' => array( 'pf_not_null', 'pf_max_input', 'pf_input_format', 'pf_search_type', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'Member' => array( 'pf_not_null', 'pf_multiple', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'Password' => array( 'pf_not_null', 'pf_max_input', 'pf_input_format', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'Select' => array( 'pf_not_null', 'pf_content', 'pf_multiple', 'pf_search_type_on_off', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'Tel' => array( 'pf_not_null', 'pf_max_input', 'pf_input_format', 'pf_search_type', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'Text' => array( 'pf_not_null', 'pf_max_input', 'pf_input_format', 'pf_search_type', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'TextArea' => array( 'pf_not_null', 'pf_max_input', 'pf_input_format', 'pf_search_type', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'Url' => array( 'pf_not_null', 'pf_max_input', 'pf_input_format', 'pf_search_type', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'Radio' => array( 'pf_content', "{$form->id}_header_pfield_displayoptions", 'pf_search_type_on_off', 'pf_format' ),
|
||||
'Address' => array( 'pf_not_null', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'Color' => array( 'pf_not_null', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'Date' => array( 'pf_not_null', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'Editor' => array( 'pf_not_null', "{$form->id}_header_pfield_displayoptions", 'pf_format', 'pf_search_type' ),
|
||||
'Number' => array( 'pf_not_null', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'Poll' => array( 'pf_not_null' ),
|
||||
'Rating' => array( 'pf_not_null' ),
|
||||
'Upload' => array( 'pf_not_null' ),
|
||||
'Rating' => array( 'pf_not_null', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
'Upload' => array( 'pf_not_null', "{$form->id}_header_pfield_displayoptions", 'pf_format' ),
|
||||
);
|
||||
foreach ( static::$additionalFieldTypes as $k => $v )
|
||||
{
|
||||
@@ -160,9 +165,6 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'pf_type', $this->id ? $this->type : 'Text', TRUE, array( 'options' => $options, 'toggles' => $toggles ) ) );
|
||||
$form->add( new \IPS\Helpers\Form\Stack( 'pf_content', $this->id ? json_decode( $this->content, TRUE ) : array(), FALSE, array( 'removeEmptyValues' => FALSE ), NULL, NULL, NULL, 'pf_content' ) );
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'pf_multiple', $this->id ? $this->multiple : FALSE, FALSE, array(), NULL, NULL, NULL, 'pf_multiple' ) );
|
||||
@@ -170,7 +172,7 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
$requiredColumn = ( isset( $this::$databaseColumnMap['not_null'] ) and $this::$databaseColumnMap['not_null'] ) ? $this::$databaseColumnMap['not_null'] : NULL;
|
||||
|
||||
$form->add( new \IPS\Helpers\Form\YesNo( 'pf_not_null', $this->id ? $this->$requiredColumn : TRUE, FALSE, array(), NULL, NULL, NULL, 'pf_not_null' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'pf_max_input', $this->id ? $this->max_input : NULL, FALSE, array( 'unlimited' => 0 ), NULL, NULL, NULL, 'pf_max_input' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Number( 'pf_max_input', $this->id ? $this->max_input : 0, FALSE, array( 'unlimited' => 0 ), NULL, NULL, NULL, 'pf_max_input' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Text( 'pf_input_format', $this->id ? $this->input_format : NULL, FALSE, array( 'placeholder' => '/[A-Z0-9]+/i' ), function( $val )
|
||||
{
|
||||
if ( $val AND @preg_match( $val, NULL ) === false )
|
||||
@@ -180,6 +182,8 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
}, NULL, NULL, 'pf_input_format' ) );
|
||||
$form->addHeader( 'pfield_displayoptions' );
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'pf_search_type', $this->id ? $this->search_type : 'loose', FALSE, array( 'options' => array( 'exact' => 'pf_search_type_exact', 'loose' => 'pf_search_type_loose', '' => 'pf_search_type_none' ) ), NULL, NULL, NULL, 'pf_search_type' ) );
|
||||
$form->add( new \IPS\Helpers\Form\Select( 'pf_search_type_on_off', $this->id ? $this->search_type : 'exact', FALSE, array( 'options' => array( 'exact' => 'pf_search_type_exact', '' => 'pf_search_type_none' ) ), NULL, NULL, NULL, 'pf_search_type_on_off' ) );
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -321,7 +325,7 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
case 'Address':
|
||||
case 'Codemirror':
|
||||
case 'Select':
|
||||
$columnDefinition['type'] = 'TEXT';
|
||||
$columnDefinition['type'] = 'MEDIUMTEXT';
|
||||
break;
|
||||
|
||||
case 'Email':
|
||||
@@ -357,7 +361,7 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
|
||||
if ( $values['pf_type'] != 'Upload' )
|
||||
{
|
||||
if ( $columnDefinition['type'] == 'TEXT' )
|
||||
if ( in_array( $columnDefinition['type'], array( 'TEXT', 'MEDIUMTEXT' ) ) )
|
||||
{
|
||||
\IPS\Db::i()->addIndex( static::$contentDatabaseTable, array( 'type' => 'fulltext', 'name' => $columnDefinition['name'], 'columns' => array( $columnDefinition['name'] ) ) );
|
||||
}
|
||||
@@ -383,7 +387,7 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
|
||||
if ( $values['pf_type'] != 'Upload' )
|
||||
{
|
||||
if ( $columnDefinition['type'] == 'TEXT' )
|
||||
if ( in_array( $columnDefinition['type'], array( 'TEXT', 'MEDIUMTEXT' ) ) )
|
||||
{
|
||||
\IPS\Db::i()->addIndex( static::$contentDatabaseTable, array( 'type' => 'fulltext', 'name' => $column, 'columns' => array( $column ) ) );
|
||||
}
|
||||
@@ -395,7 +399,18 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Db::i()->dropIndex( static::$contentDatabaseTable, $column );
|
||||
|
||||
\IPS\Db::i()->changeColumn( static::$contentDatabaseTable, $column, $columnDefinition );
|
||||
|
||||
if ( in_array( $columnDefinition['type'], array( 'TEXT', 'MEDIUMTEXT' ) ) )
|
||||
{
|
||||
\IPS\Db::i()->addIndex( static::$contentDatabaseTable, array( 'type' => 'fulltext', 'name' => $column, 'columns' => array( $column ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
\IPS\Db::i()->addIndex( static::$contentDatabaseTable, array( 'type' => 'key', 'name' => $column, 'columns' => array( $column ) ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ( !$this->id )
|
||||
@@ -427,11 +442,18 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
{
|
||||
$values['pf_not_null'] = FALSE;
|
||||
}
|
||||
|
||||
|
||||
if ( isset( $values['pf_search_type_on_off'] ) and isset( $values['pf_type'] ) and ( $values['pf_type'] == 'Select' or $values['pf_type'] == 'Radio' ) )
|
||||
{
|
||||
$values['pf_search_type'] = $values['pf_search_type_on_off'];
|
||||
}
|
||||
|
||||
unset( $values['pf_search_type_on_off'] );
|
||||
|
||||
/* Translate keys */
|
||||
foreach ( array( 'type', 'content', 'multiple', 'not_null', 'max_input', 'input_format', 'search_type', 'format' ) as $k )
|
||||
{
|
||||
if ( isset( $values[ "pf_{$k}" ] ) )
|
||||
if ( array_key_exists( "pf_{$k}", $values ) )
|
||||
{
|
||||
$_value = $values[ "pf_{$k}" ];
|
||||
unset( $values[ "pf_{$k}" ] );
|
||||
@@ -507,7 +529,7 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
|
||||
if ( $this->type != 'Upload' )
|
||||
{
|
||||
if ( $fieldDefinition['type'] == 'TEXT' )
|
||||
if ( in_array( $fieldDefinition['type'], array( 'TEXT', 'MEDIUMTEXT' ) ) )
|
||||
{
|
||||
\IPS\Db::i()->addIndex( static::$contentDatabaseTable, array( 'type' => 'fulltext', 'name' => $column, 'columns' => array( $column ) ) );
|
||||
}
|
||||
@@ -552,7 +574,13 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
public function buildHelper( $value=NULL, $customValidationCode=NULL )
|
||||
{
|
||||
$class = '\IPS\Helpers\Form\\' . $this->type;
|
||||
|
||||
|
||||
/* Hooks can add custom field types which are stored in the database. Toggling the hook can then stop the hook from loading the field class giving a class not found error */
|
||||
if ( ! class_exists( $class ) )
|
||||
{
|
||||
$class = '\IPS\Helpers\Form\\Text';
|
||||
}
|
||||
|
||||
$options = array();
|
||||
switch ( $this->type )
|
||||
{
|
||||
@@ -588,7 +616,7 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
{
|
||||
if( $value !== NULL AND $value !== '' )
|
||||
{
|
||||
$value = explode( ',', htmlspecialchars( $value, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) );
|
||||
$value = explode( ',', htmlspecialchars( $value, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ) );
|
||||
}
|
||||
|
||||
$options['multiple'] = $this->multiple;
|
||||
@@ -601,7 +629,8 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
$requiredColumn = ( isset( $this::$databaseColumnMap['not_null'] ) and $this::$databaseColumnMap['not_null'] ) ? $this::$databaseColumnMap['not_null'] : NULL;
|
||||
if ( !$this->$requiredColumn AND !$this->multiple )
|
||||
{
|
||||
array_unshift( $options['options'], '' );
|
||||
/* We cannot use array_unshift because it reindexes numerical indexes, which breaks custom field options */
|
||||
$options['options'] = array( '' ) + $options['options'];
|
||||
}
|
||||
|
||||
if ( $this->multiple )
|
||||
@@ -610,11 +639,31 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
|
||||
if( $value !== NULL AND $value !== '' )
|
||||
{
|
||||
$value = explode( ',', $value );
|
||||
$values = explode( ',', $value );
|
||||
$value = array();
|
||||
foreach( $values as $val )
|
||||
{
|
||||
if ( is_numeric( $val ) and intval( $val ) == $val )
|
||||
{
|
||||
$value[] = intval( $val );
|
||||
}
|
||||
else
|
||||
{
|
||||
$value[] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$options['multiple'] = $this->multiple;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( is_numeric( $value ) and intval( $value ) == $value )
|
||||
{
|
||||
$value = intval( $value );
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'Radio':
|
||||
@@ -657,7 +706,7 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
$value = array_map( function( $id )
|
||||
{
|
||||
return \IPS\Member::load( $id );
|
||||
}, explode( ',', $value ) );
|
||||
}, explode( "\n", $value ) );
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -674,6 +723,10 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'Ftp':
|
||||
$options['allowBypassValidation'] = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Editor form field names and IDs should differ */
|
||||
@@ -691,9 +744,10 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
* Claim attachments for an editor field
|
||||
*
|
||||
* @param int|NULL $id1 ID 1 (ID 2 will be the field ID)
|
||||
* @param mixed $id3 ID 3
|
||||
* @return void
|
||||
*/
|
||||
public function claimAttachments( $id1 = NULL )
|
||||
public function claimAttachments( $id1 = NULL, $id3 = NULL )
|
||||
{
|
||||
$options = static::$editorOptions;
|
||||
|
||||
@@ -702,7 +756,7 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
$options['autoSaveKey'] = md5( get_class( $this ) . '-' . $this->id );
|
||||
}
|
||||
|
||||
\IPS\File::claimAttachments( $options['autoSaveKey'], $id1, $this->id );
|
||||
\IPS\File::claimAttachments( $options['autoSaveKey'], $id1, $this->id, $id3 );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -724,7 +778,7 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
|
||||
case 'CheckboxSet':
|
||||
case 'Select':
|
||||
if ( isset( $this->extra[ $value ] ) )
|
||||
if ( is_array( $this->extra ) AND isset( $this->extra[ $value ] ) )
|
||||
{
|
||||
$value = $this->extra[ $value ];
|
||||
}
|
||||
@@ -732,6 +786,18 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
{
|
||||
$options = json_decode( $this->content, TRUE );
|
||||
|
||||
/* Options are based on numeric indices, however when creating the original form field we may have added
|
||||
a dummy option to the beginning - we need to do the same here or else index '5' is not the same index '5'
|
||||
we originally selected from the form element */
|
||||
if( $this->type == 'Select' )
|
||||
{
|
||||
$requiredColumn = ( isset( $this::$databaseColumnMap['not_null'] ) and $this::$databaseColumnMap['not_null'] ) ? $this::$databaseColumnMap['not_null'] : NULL;
|
||||
if ( !$this->$requiredColumn AND !$this->multiple )
|
||||
{
|
||||
array_unshift( $options, '' );
|
||||
}
|
||||
}
|
||||
|
||||
if( $this->multiple )
|
||||
{
|
||||
$_values = array();
|
||||
@@ -751,11 +817,11 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
|
||||
if ( $this->multiple )
|
||||
{
|
||||
return implode( '<br>', explode( ',', htmlspecialchars( $value, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) ) );
|
||||
return implode( '<br>', explode( ',', htmlspecialchars( $value, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ) ) );
|
||||
}
|
||||
else
|
||||
{
|
||||
return htmlspecialchars( \IPS\Lang::wordbreak( $value ), \IPS\HTMLENTITIES, 'UTF-8', FALSE );
|
||||
return htmlspecialchars( $value, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE );
|
||||
}
|
||||
|
||||
case 'Codemirror':
|
||||
@@ -765,7 +831,7 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
return \IPS\Theme::i()->getTemplate( 'forms', 'core', 'global' )->colorDisplay( $value );
|
||||
|
||||
case 'Date':
|
||||
return \IPS\Lang::wordbreak( \IPS\DateTime::ts( $value, TRUE )->localeDate() ); // See buildHelper for why we ignore the timezone
|
||||
return \IPS\DateTime::ts( $value, TRUE )->localeDate(); // See buildHelper for why we ignore the timezone
|
||||
|
||||
case 'Editor':
|
||||
return $value;
|
||||
@@ -774,7 +840,7 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
return implode( '<br>', array_map( function( $id )
|
||||
{
|
||||
return \IPS\Member::load( $id )->link();
|
||||
}, explode( ',', $value ) ) );
|
||||
}, explode( "\n", $value ) ) );
|
||||
|
||||
case 'Poll':
|
||||
return $value ? ( (string) \IPS\Poll::load( $value ) ) : NULL;
|
||||
@@ -783,21 +849,28 @@ abstract class _CustomField extends \IPS\Node\Model
|
||||
return \IPS\Theme::i()->getTemplate( 'global', 'core', 'front' )->rating( $this->options['max'], $value );
|
||||
|
||||
case 'TextArea':
|
||||
return \IPS\Lang::wordbreak( nl2br( htmlspecialchars( $value, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) ) );
|
||||
return nl2br( htmlspecialchars( $value, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE ) );
|
||||
|
||||
case 'Url':
|
||||
$munged = ( $value ) ? \IPS\Http\Url::external( $value )->makeSafeForAcp() : NULL;
|
||||
return ( $value ) ? \IPS\Theme::i()->getTemplate( 'global', 'core', 'global' )->basicUrl( $munged, TRUE, $value ) : NULL;
|
||||
|
||||
case 'Upload':
|
||||
return \IPS\Theme::i()->getTemplate( 'forms', 'core', 'global' )->uploadDisplay( \IPS\File::get( static::$uploadStorageExtension, $value ) );
|
||||
$file = \IPS\File::get( static::$uploadStorageExtension, $value );
|
||||
$downloadUrl = \IPS\Http\Url::internal( 'applications/core/interface/file/cfield.php', 'none' )->setqueryString( array(
|
||||
'storage' => $file->storageExtension,
|
||||
'path' => (string) $file,
|
||||
) );
|
||||
return \IPS\Theme::i()->getTemplate( 'forms', 'core', 'global' )->uploadDisplay( $file, $downloadUrl );
|
||||
|
||||
case 'Ftp':
|
||||
return \IPS\Theme::i()->getTemplate( 'forms', 'core', 'global' )->ftpDisplay( $value );
|
||||
$value = is_array( $value ) ? $value : json_decode( \IPS\Text\Encrypt::fromTag( $value )->decrypt(), TRUE );
|
||||
$url = \IPS\Http\Url::createFromComponents( $value['server'], $value['protocol'] ? ( $value['protocol'] == 'ssl_ftp' ? 'ftps': $value['protocol'] ) : 'ftp', $value['path'] ?: NULL, NULL, $value['port'] ?: 21, $value['un'] ?: NULL, $value['pw'] ?: NULL );
|
||||
return \IPS\Theme::i()->getTemplate( 'forms', 'core', 'global' )->ftpDisplay( $value, $url );
|
||||
|
||||
|
||||
default:
|
||||
return \IPS\Lang::wordbreak( htmlspecialchars( $value, \IPS\HTMLENTITIES, 'UTF-8', FALSE ) );
|
||||
return htmlspecialchars( $value, \IPS\HTMLENTITIES | ENT_QUOTES, 'UTF-8', FALSE );
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user