Skip to content

Commit

Permalink
Fix EZP-22480: Object creation does not respect attribute constraints…
Browse files Browse the repository at this point in the history
… in ezoe
  • Loading branch information
dpobel committed Mar 17, 2014
1 parent ec94ea0 commit b6f895e
Show file tree
Hide file tree
Showing 9 changed files with 238 additions and 124 deletions.
@@ -1,9 +1,12 @@
{if is_unset( $file_name_attribute )}
{def $file_name_attribute = ''}
{/if}
{if is_unset( $objectname_input_name )}
{def $objectname_input_name = 'objectName'}
{/if}
<tr>
<td class="column1"><label id="titlelabel" for="objectName">{'Name'|i18n('design/standard/ezoe')}</label></td>
<td colspan="2"><input id="objectName" name="objectName" size="40" type="text" value="" title="{'Name for the uploaded object, filename is used if none is specified.'|i18n('design/standard/ezoe/wai')}" /></td>
<td colspan="2"><input id="objectName" name="{$objectname_input_name|wash()}" size="40" type="text" value="" title="{'Name for the uploaded object, filename is used if none is specified.'|i18n('design/standard/ezoe/wai')}" /></td>
</tr>
<tr>
<td class="column1"><label id="srclabel" for="fileName">{'File'|i18n('design/standard/ezoe')}</label></td>
Expand Down
Expand Up @@ -52,7 +52,7 @@ tinyMCEPopup.onInit.add( function(){
<div class="panel">
<table class="properties">
{include uri="design:ezoe/upload/common_attributes.tpl"}
{include uri="design:ezoe/upload/common_attributes.tpl" objectname_input_name='ContentObjectAttribute_name'}
<!-- Next attribute is file / media specific -->
<tr>
Expand Down
Expand Up @@ -61,7 +61,7 @@ eZOEPopupUtils.settings.browseClassGenerator = function( n, hasImage ){
<div class="panel">
<table class="properties">
{include uri="design:ezoe/upload/common_attributes.tpl" file_name_attribute='accept="image/*"'}
{include uri="design:ezoe/upload/common_attributes.tpl" objectname_input_name='ContentObjectAttribute_name' file_name_attribute='accept="image/*"'}
<!-- Next two attributes are image specific -->
<tr>
Expand Down
Expand Up @@ -52,7 +52,7 @@ tinyMCEPopup.onInit.add( function(){
<div class="panel">
<table class="properties">
{include uri="design:ezoe/upload/common_attributes.tpl"}
{include uri="design:ezoe/upload/common_attributes.tpl" objectname_input_name='ContentObjectAttribute_name'}
<!-- Next attribute is file / media specific -->
<tr>
Expand Down
131 changes: 80 additions & 51 deletions extension/ezoe/modules/ezoe/upload.php
Expand Up @@ -104,93 +104,122 @@
$objectName = trim( $http->postVariable( 'objectName' ) );
}

$uploadedOk = $upload->handleUpload(
$result,
'fileName',
$location,
false,
$objectName,
$version->attribute( 'initial_language' )->attribute( 'locale' )
);


if ( $uploadedOk )
try
{
$newObject = $result['contentobject'];
$newObjectID = $newObject->attribute( 'id' );
$newObjectName = $newObject->attribute( 'name' );
$newObjectNodeID = (int) $newObject->attribute( 'main_node_id' ); // this will be empty if object is stopped by approve workflow

// set parent section for new object
if ( isset( $newObjectNodeID ) && $newObjectNodeID )
$uploadedOk = $upload->handleUpload(
$result,
'fileName',
$location,
false,
$objectName,
$version->attribute( 'initial_language' )->attribute( 'locale' ),
false
);
if ( !$uploadedOk )
{
$newObjectParentNodeObject = $newObject->attribute( 'main_node' )->attribute( 'parent' )->attribute( 'object' );
$newObject->setAttribute( 'section_id', $newObjectParentNodeObject->attribute( 'section_id' ) );
$newObject->store();
throw new RuntimeException( "Upload failed" );
}

// edit attributes
$newVersionObject = $newObject->attribute( 'current' );
$newObjectDataMap = $newVersionObject->attribute('data_map');
$uploadVersion = $uploadedOk['contentobject']->currentVersion();
$newObjectID = $uploadedOk['contentobject']->attribute( 'id' );

foreach ( array_keys( $newObjectDataMap ) as $key )
foreach ( $uploadVersion->dataMap() as $key => $attr )
{
//post pattern: ContentObjectAttribute_attribute-identifier
$base = 'ContentObjectAttribute_'. $key;
if ( $http->hasPostVariable( $base ) && $http->postVariable( $base ) !== '' )
$postVar = trim( $http->postVariable( $base, '' ) );
if ( $postVar !== '' )
{
switch ( $newObjectDataMap[$key]->attribute( 'data_type_string' ) )
switch ( $attr->attribute( 'data_type_string' ) )
{
case 'eztext':
case 'ezstring':
// TODO: Validate input ( max length )
$newObjectDataMap[$key]->setAttribute('data_text', trim( $http->postVariable( $base ) ) );
$newObjectDataMap[$key]->store();
$classAttr = $attr->attribute( 'contentclass_attribute' );
$dataType = $classAttr->attribute( 'data_type' );
if ( $dataType->validateStringHTTPInput( $postVar, $attr, $classAttr ) !== eZInputValidator::STATE_ACCEPTED )
{
throw new InvalidArgumentException( $attr->validationError() );
}
case 'eztext':
case 'ezkeyword':
$attr->fromString( $postVar );
$attr->store();
break;
case 'ezfloat':
// TODO: Validate input ( max / min values )
$newObjectDataMap[$key]->setAttribute('data_float', (float) str_replace(',', '.', $http->postVariable( $base ) ) );
$newObjectDataMap[$key]->store();
$floatValue = (float)str_replace( ',', '.', $postVar );
$classAttr = $attr->attribute( 'contentclass_attribute' );
$dataType = $classAttr->attribute( 'data_type' );
if ( $dataType->validateFloatHTTPInput( $floatValue, $attr, $classAttr ) !== eZInputValidator::STATE_ACCEPTED )
{
throw new InvalidArgumentException( $attr->validationError() );
}
$attr->setAttribute( 'data_float', $floatValue );
$attr->store();
break;
case 'ezinteger':
// TODO: Validate input ( max / min values )
$classAttr = $attr->attribute( 'contentclass_attribute' );
$dataType = $classAttr->attribute( 'data_type' );
if ( $dataType->validateIntegerHTTPInput( $postVar, $attr, $classAttr ) !== eZInputValidator::STATE_ACCEPTED )
{
throw new InvalidArgumentException( $attr->validationError() );
}
case 'ezboolean':
$newObjectDataMap[$key]->setAttribute('data_int', (int) $http->postVariable( $base ) );
$newObjectDataMap[$key]->store();
$attr->setAttribute( 'data_int', (int)$postVar );
$attr->store();
break;
case 'ezimage':
$content = $newObjectDataMap[$key]->attribute('content');
$content->setAttribute( 'alternative_text', trim( $http->postVariable( $base ) ) );
$content->store( $newObjectDataMap[$key] );
break;
case 'ezkeyword':
$newObjectDataMap[$key]->fromString( $http->postVariable( $base ) );
$newObjectDataMap[$key]->store();
// validation has been done by eZContentUpload
$content = $attr->attribute( 'content' );
$content->setAttribute( 'alternative_text', $postVar );
$content->store( $attr );
break;
case 'ezxmltext':
$text = trim( $http->postVariable( $base ) );
$parser = new eZOEInputParser();
$document = $parser->process( $text );
$document = $parser->process( $postVar );
$xmlString = eZXMLTextType::domString( $document );
$newObjectDataMap[$key]->setAttribute( 'data_text', $xmlString );
$newObjectDataMap[$key]->store();
$attr->setAttribute( 'data_text', $xmlString );
$attr->store();
break;
}
}
}

$object->addContentObjectRelation( $newObjectID, $objectVersion, 0, eZContentObject::RELATION_EMBED );
$operationResult = eZOperationHandler::execute(
'content', 'publish',
array(
'object_id' => $newObjectID,
'version' => $uploadVersion->attribute( 'version' )
)
);
$newObject = eZContentObject::fetch( $newObjectID );
$newObjectName = $newObject->attribute( 'name' );
$newObjectNodeID = (int)$newObject->attribute( 'main_node_id' );

$object->addContentObjectRelation(
$newObjectID,
$uploadVersion->attribute( 'version' ),
0,
eZContentObject::RELATION_EMBED
);
echo '<html><head><title>HiddenUploadFrame</title><script type="text/javascript">';
echo 'window.parent.eZOEPopupUtils.selectByEmbedId( ' . $newObjectID . ', ' . $newObjectNodeID . ', "' . $newObjectName . '" );';
echo '</script></head><body></body></html>';
}
else
catch ( InvalidArgumentException $e )
{
$uploadedOk['contentobject']->purge();
echo '<html><head><title>HiddenUploadFrame</title><script type="text/javascript">';
echo 'window.parent.document.getElementById("upload_in_progress").style.display = "none";';
echo '</script></head><body><div style="position:absolute; top: 0px; left: 0px;background-color: white; width: 100%;">';
echo '<p style="margin: 0; padding: 3px; color: red">' . htmlspecialchars( $e->getMessage() ) . '</p>';
echo '</div></body></html>';
}
catch ( RuntimeException $e )
{
echo '<html><head><title>HiddenUploadFrame</title><script type="text/javascript">';
echo 'window.parent.document.getElementById("upload_in_progress").style.display = "none";';
echo '</script></head><body><div style="position:absolute; top: 0px; left: 0px;background-color: white; width: 100%;">';
foreach( $result['errors'] as $err )
echo '<p style="margin: 0; padding: 3px; color: red">' . $err['description'] . '</p>';
echo '<p style="margin: 0; padding: 3px; color: red">' . htmlspecialchars( $err['description'] ) . '</p>';
echo '</div></body></html>';
}
eZDB::checkTransactionCounter();
Expand Down
143 changes: 94 additions & 49 deletions kernel/classes/datatypes/ezfloat/ezfloattype.php
Expand Up @@ -83,6 +83,96 @@ function fetchObjectAttributeHTTPInput( $http, $base, $contentObjectAttribute )
return false;
}

/**
* Validates $data with the constraints defined on the class attribute
*
* @param $data
* @param eZContentObjectAttribute $contentObjectAttribute
* @param eZContentClassAttribute $classAttribute
*
* @return int
*/
function validateFloatHTTPInput( $data, $contentObjectAttribute, $classAttribute )
{
$min = $classAttribute->attribute( self::MIN_FIELD );
$max = $classAttribute->attribute( self::MAX_FIELD );
$inputState = $classAttribute->attribute( self::INPUT_STATE_FIELD );
switch( $inputState )
{
case self::NO_MIN_MAX_VALUE:
$state = $this->FloatValidator->validate( $data );
if ( $state === eZInputValidator::STATE_ACCEPTED )
{
return eZInputValidator::STATE_ACCEPTED;
}
else
{
$contentObjectAttribute->setValidationError(
ezpI18n::tr(
'kernel/classes/datatypes',
'The given input is not a floating point number.'
)
);
}
break;
case self::HAS_MIN_VALUE:
$this->FloatValidator->setRange( $min, false );
$state = $this->FloatValidator->validate( $data );
if ( $state === eZInputValidator::STATE_ACCEPTED )
{
return eZInputValidator::STATE_ACCEPTED;
}
else
{
$contentObjectAttribute->setValidationError(
ezpI18n::tr(
'kernel/classes/datatypes',
'The input must be greater than %1'
),
$min
);
}
break;
case self::HAS_MAX_VALUE:
$this->FloatValidator->setRange( false, $max );
$state = $this->FloatValidator->validate( $data );
if ( $state === eZInputValidator::STATE_ACCEPTED )
{
return eZInputValidator::STATE_ACCEPTED;
}
else
{
$contentObjectAttribute->setValidationError(
ezpI18n::tr(
'kernel/classes/datatypes',
'The input must be less than %1'
),
$max
);
}
break;
case self::HAS_MIN_MAX_VALUE:
$this->FloatValidator->setRange( $min, $max );
$state = $this->FloatValidator->validate( $data );
if ( $state === eZInputValidator::STATE_ACCEPTED )
{
return eZInputValidator::STATE_ACCEPTED;
}
else
{
$contentObjectAttribute->setValidationError(
ezpI18n::tr(
'kernel/classes/datatypes',
'The input is not in defined range %1 - %2'
),
$min, $max
);
}
break;
}
return eZInputValidator::STATE_INVALID;
}

/*!
Validates the input and returns true if the input was
valid for this datatype.
Expand All @@ -93,10 +183,6 @@ function validateObjectAttributeHTTPInput( $http, $base, $contentObjectAttribute
{
$data = $http->postVariable( $base . "_data_float_" . $contentObjectAttribute->attribute( "id" ) );
$data = str_replace(" ", "", $data );
$classAttribute = $contentObjectAttribute->contentClassAttribute();
$min = $classAttribute->attribute( self::MIN_FIELD );
$max = $classAttribute->attribute( self::MAX_FIELD );
$input_state = $classAttribute->attribute( self::INPUT_STATE_FIELD );

if ( !$contentObjectAttribute->validateIsRequired() && ( $data == "" ) )
{
Expand All @@ -106,51 +192,10 @@ function validateObjectAttributeHTTPInput( $http, $base, $contentObjectAttribute
$locale = eZLocale::instance();
$data = $locale->internalNumber( $data );

switch( $input_state )
{
case self::NO_MIN_MAX_VALUE:
{
$state = $this->FloatValidator->validate( $data );
if( $state===1 )
return eZInputValidator::STATE_ACCEPTED;
else
$contentObjectAttribute->setValidationError( ezpI18n::tr( 'kernel/classes/datatypes',
'The given input is not a floating point number.' ) );
} break;
case self::HAS_MIN_VALUE:
{
$this->FloatValidator->setRange( $min, false );
$state = $this->FloatValidator->validate( $data );
if( $state===1 )
return eZInputValidator::STATE_ACCEPTED;
else
$contentObjectAttribute->setValidationError( ezpI18n::tr( 'kernel/classes/datatypes',
'The input must be greater than %1' ),
$min );
} break;
case self::HAS_MAX_VALUE:
{
$this->FloatValidator->setRange( false, $max );
$state = $this->FloatValidator->validate( $data );
if( $state===1 )
return eZInputValidator::STATE_ACCEPTED;
else
$contentObjectAttribute->setValidationError( ezpI18n::tr( 'kernel/classes/datatypes',
'The input must be less than %1' ),
$max );
} break;
case self::HAS_MIN_MAX_VALUE:
{
$this->FloatValidator->setRange( $min, $max );
$state = $this->FloatValidator->validate( $data );
if( $state===1 )
return eZInputValidator::STATE_ACCEPTED;
else
$contentObjectAttribute->setValidationError( ezpI18n::tr( 'kernel/classes/datatypes',
'The input is not in defined range %1 - %2' ),
$min, $max );
} break;
}
return $this->validateFloatHTTPInput(
$data, $contentObjectAttribute,
$contentObjectAttribute->contentClassAttribute()
);
}
return eZInputValidator::STATE_INVALID;
}
Expand Down
12 changes: 9 additions & 3 deletions kernel/classes/datatypes/ezinteger/ezintegertype.php
Expand Up @@ -43,9 +43,15 @@ function eZIntegerType()
$this->IntegerValidator = new eZIntegerValidator();
}

/*!
Private method, only for using inside this class.
*/
/**
* Validates $data with the constraints defined on the class attribute
*
* @param $data
* @param eZContentObjectAttribute $contentObjectAttribute
* @param eZContentClassAttribute $classAttribute
*
* @return int
*/
function validateIntegerHTTPInput( $data, $contentObjectAttribute, $classAttribute )
{
$min = $classAttribute->attribute( self::MIN_VALUE_FIELD );
Expand Down

0 comments on commit b6f895e

Please sign in to comment.