|
eZ Publish
[trunk]
|
00001 <?php 00002 /** 00003 * File containing the eZImageAliasHandler class. 00004 * 00005 * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved. 00006 * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2 00007 * @version //autogentag// 00008 * @package kernel 00009 */ 00010 00011 /*! 00012 \class eZImageAliasHandler ezimagealiashandler.php 00013 \ingroup eZDatatype 00014 \brief Internal manager for the eZImage datatype 00015 00016 Takes care of image conversion and serialization from and to 00017 the internal XML format. 00018 00019 \note This handler was introduced in eZ Publish 3.3 and will detect older 00020 eZImage structures and convert them on the fly. 00021 00022 \note The XML storage was improved in 3.8, from then it always stores the 00023 attribute ID, version and language in the <original> tag. 00024 This was required to get the new multi-language features to work. 00025 */ 00026 00027 class eZImageAliasHandler 00028 { 00029 /*! 00030 Creates the handler and creates a reference to the contentobject attribute that created it. 00031 */ 00032 function eZImageAliasHandler( $contentObjectAttribute ) 00033 { 00034 $this->ContentObjectAttributeData = array(); 00035 if ( is_object( $contentObjectAttribute ) ) 00036 { 00037 $this->ContentObjectAttributeData['id'] = $contentObjectAttribute->attribute( 'id' ); 00038 $this->ContentObjectAttributeData['contentobject_id'] = $contentObjectAttribute->attribute( 'contentobject_id' ); 00039 $this->ContentObjectAttributeData['version'] = $contentObjectAttribute->attribute( 'version' ); 00040 $this->ContentObjectAttributeData['language_code'] = $contentObjectAttribute->attribute( 'language_code' ); 00041 $this->ContentObjectAttributeData['can_translate'] = $contentObjectAttribute->attribute( 'can_translate' ); 00042 $this->ContentObjectAttributeData['data_text'] = $contentObjectAttribute->attribute( 'data_text' ); 00043 $this->ContentObjectAttributeData['DataTypeCustom'] = $contentObjectAttribute->DataTypeCustom; 00044 if ( !is_array( $this->ContentObjectAttributeData['DataTypeCustom'] ) ) 00045 { 00046 $this->ContentObjectAttributeData['DataTypeCustom'] = array(); 00047 } 00048 } 00049 else 00050 { 00051 eZDebug::writeWarning( 'Invalid eZContentObjectAttribute', __METHOD__ ); 00052 } 00053 } 00054 00055 /*! 00056 Lists all available image aliases as attributes as well as: 00057 - alternative_text - The alternative text input by the user, can be empty 00058 - original_filename - The name of image which it had on the users disk before it was uploaded 00059 - is_valid - A boolean which says if there is an image here or not. 00060 */ 00061 function attributes() 00062 { 00063 $imageManager = eZImageManager::factory(); 00064 $aliasList = $imageManager->aliasList(); 00065 return array_merge( array( 'alternative_text', 00066 'original_filename', 00067 'is_valid' ), 00068 array_keys( $aliasList ) ); 00069 } 00070 00071 /*! 00072 \return true if the attribute named \a $attributeName exists. 00073 See eZImageAliasHandler::attributes() for which attributes are available. 00074 */ 00075 function hasAttribute( $attributeName ) 00076 { 00077 if ( in_array( $attributeName, 00078 array( 'alternative_text', 00079 'original_filename', 00080 'is_valid' ) ) ) 00081 return true; 00082 00083 $imageManager = eZImageManager::factory(); 00084 if ( $imageManager->hasAlias( $attributeName ) ) 00085 return true; 00086 return false; 00087 } 00088 00089 /*! 00090 \return the value of the attribute named \a $attributeName. 00091 See eZImageAliasHandler::attributes() for which attributes are available. 00092 */ 00093 function attribute( $attributeName ) 00094 { 00095 if ( in_array( $attributeName, 00096 array( 'alternative_text', 00097 'original_filename', 00098 'is_valid' ) ) ) 00099 { 00100 return $this->attributeFromOriginal( $attributeName ); 00101 } 00102 $aliasName = $attributeName; 00103 return $this->imageAlias( $aliasName ); 00104 } 00105 00106 /*! 00107 \return The value of the attribute named \a $attributeName from the 'original' image alias. 00108 00109 This is a quick way for extracting information from the 'original' image alias. 00110 */ 00111 function &attributeFromOriginal( $attributeName ) 00112 { 00113 $originalAlias = $this->attribute( 'original' ); 00114 if ( $originalAlias ) 00115 return $originalAlias[$attributeName]; 00116 $retValue = null; 00117 return $retValue; 00118 } 00119 00120 /*! 00121 Sets the attribute named \a $attributeName to have the value \a $attributeValue. 00122 00123 The following attributes can be set: 00124 - alternative text 00125 - original_filename 00126 */ 00127 function setAttribute( $attributeName, $attributeValue ) 00128 { 00129 if ( in_array( $attributeName, 00130 array( 'alternative_text', 00131 'original_filename' ) ) ) 00132 { 00133 $aliasList = $this->aliasList(); 00134 foreach ( array_keys( $aliasList ) as $aliasName ) 00135 { 00136 $this->setAliasAttribute( $aliasName, $attributeName, $attributeValue ); 00137 } 00138 if ( $attributeName == 'alternative_text' ) 00139 { 00140 $text = $this->displayText( $attributeValue ); 00141 foreach ( array_keys( $aliasList ) as $aliasName ) 00142 { 00143 $this->setAliasAttribute( $aliasName, 'text', $text ); 00144 } 00145 } 00146 $this->recreateDOMTree(); 00147 $this->setStorageRequired(); 00148 return true; 00149 } 00150 return false; 00151 } 00152 00153 /*! 00154 \return \c true if this is considered to be owner of the image. 00155 00156 It will be considered an owner if attribute data is not a copy 00157 of another attribute. For instance each time a new image is uploaded 00158 this will return \c true. 00159 */ 00160 function isImageOwner() 00161 { 00162 $originalData = $this->originalAttributeData(); 00163 return ( $originalData['attribute_id'] == false || 00164 ( $originalData['attribute_id'] == $this->ContentObjectAttributeData['id'] && 00165 $originalData['attribute_version'] == $this->ContentObjectAttributeData['version'] && 00166 $originalData['attribute_language'] == $this->ContentObjectAttributeData['language_code'] ) ); 00167 } 00168 00169 /*! 00170 \return The current serial number, the value will be 1 or higher. 00171 00172 The serial number is used to create unique filenames for uploaded images, 00173 it will be increased each time an image is uploaded. 00174 00175 00176 \note This was required to get around the problem where browsers 00177 caches image information, if two images were uploaded in one version (e.g. a draft) 00178 the browser would not load the new image since it thought it had not changed. 00179 */ 00180 function imageSerialNumber() 00181 { 00182 $serialNumber = $this->imageSerialNumberRaw(); 00183 if ( $serialNumber < 1 ) 00184 { 00185 $serialNumber = 1; 00186 } 00187 return $serialNumber; 00188 } 00189 00190 /*! 00191 Increases the serial by one. 00192 */ 00193 function increaseImageSerialNumber() 00194 { 00195 $this->setImageSerialNumber( $this->imageSerialNumberRaw() + 1 ); 00196 } 00197 00198 /*! 00199 Resets the serial number to zero. 00200 */ 00201 function resetImageSerialNumber() 00202 { 00203 $this->setImageSerialNumber( 0 ); 00204 } 00205 00206 /*! 00207 \return A text string which can be used as display for the image. 00208 00209 The text string will either contain the alternative text from the attribute 00210 or the parameter \a $alternativeText if it is set. 00211 */ 00212 function displayText( $alternativeText = null ) 00213 { 00214 if ( $alternativeText === null ) 00215 $text = $this->attribute( 'alternative_text' ); 00216 else 00217 $text = $alternativeText; 00218 00219 return $text; 00220 } 00221 00222 /*! 00223 \return The full directory path to the image, this includes the var and storage directory. 00224 */ 00225 function directoryPath() 00226 { 00227 $aliasList = $this->aliasList(); 00228 if ( isset( $aliasList['original'] ) ) 00229 { 00230 return $aliasList['original']['dirpath']; 00231 } 00232 return false; 00233 } 00234 00235 /*! 00236 \return A normalized name for the image. 00237 00238 The image name will generated from the name of the current version. 00239 If this is empty it will use the object name or the alternative text. 00240 00241 This ensures that the image has a name which corresponds to the object it belongs to. 00242 00243 The normalization ensures that the name only contains filename and URL friendly characters. 00244 */ 00245 function imageName( $contentObjectAttribute, $contentVersion, $language = false ) 00246 { 00247 if ( $language === false ) 00248 { 00249 if ( is_object( $contentObjectAttribute ) ) // for backward compatibility when eZImageAliasHandler used $this->contentObjectAttribute 00250 { 00251 $language = $contentObjectAttribute->attribute( 'language_code' ); 00252 } 00253 else 00254 { 00255 $language = $contentObjectAttribute['language_code']; 00256 } 00257 } 00258 $objectName = $contentVersion->versionName( $language ); 00259 if ( !$objectName ) 00260 { 00261 $objectName = $contentVersion->name( $language ); 00262 if ( !$objectName ) 00263 { 00264 $objectName = $this->attribute( 'alternative_text' ); 00265 if ( !$objectName ) 00266 { 00267 $objectName = ezpI18n::tr( 'kernel/classes/datatypes', 'image', 'Default image name' ); 00268 } 00269 } 00270 } 00271 $objectName = eZImageAliasHandler::normalizeImageName( $objectName ); 00272 $objectName .= $this->imageSerialNumber(); 00273 00274 return $objectName; 00275 } 00276 00277 /*! 00278 \return A normalized name for the image based on a node. 00279 00280 Similar to \a imageName() but fetches name information from the node \a $mainNode. 00281 00282 The normalization ensures that the name only contains filename and URL friendly characters. 00283 */ 00284 function imageNameByNode( $contentObjectAttribute, $mainNode, $language = false ) 00285 { 00286 if ( $language === false ) 00287 { 00288 if ( is_object( $contentObjectAttribute ) ) // for backward compatibility when eZImageAliasHandler used $this->contentObjectAttribute 00289 { 00290 $language = $contentObjectAttribute->attribute( 'language_code' ); 00291 } 00292 else 00293 { 00294 $language = $contentObjectAttribute['language_code']; 00295 } 00296 } 00297 $objectName = $mainNode->getName( $language ); 00298 if ( !$objectName ) 00299 { 00300 $objectName = $this->attribute( 'alternative_text' ); 00301 if ( !$objectName ) 00302 { 00303 $objectName = ezpI18n::tr( 'kernel/classes/datatypes', 'image', 'Default image name' ); 00304 } 00305 } 00306 $objectName = eZImageAliasHandler::normalizeImageName( $objectName ); 00307 return $objectName; 00308 } 00309 00310 /*! 00311 \return The storage path for the image. 00312 00313 The path is calculated by using information from the current object and version. 00314 If the object is in the node tree it will contain a path that matches the node path, 00315 if not it will be placed in the versioned storage repository. 00316 */ 00317 function imagePath( $contentObjectAttribute, $contentVersion, $isImageOwner = null ) 00318 { 00319 $useVersion = false; 00320 if ( $isImageOwner === null ) 00321 $isImageOwner = $this->isImageOwner(); 00322 if ( $contentVersion->attribute( 'status' ) == eZContentObjectVersion::STATUS_PUBLISHED or 00323 !$isImageOwner ) 00324 { 00325 $contentObject = $contentVersion->attribute( 'contentobject' ); 00326 $mainNode = $contentObject->attribute( 'main_node' ); 00327 if ( !$mainNode ) 00328 { 00329 $ini = eZINI::instance( 'image.ini' ); 00330 $contentImageSubtree = $ini->variable( 'FileSettings', 'VersionedImages' ); 00331 $pathString = $contentImageSubtree; 00332 $useVersion = true; 00333 } 00334 else 00335 { 00336 $ini = eZINI::instance( 'image.ini' ); 00337 $contentImageSubtree = $ini->variable( 'FileSettings', 'PublishedImages' ); 00338 $pathString = $mainNode->pathWithNames(); 00339 $pathString = function_exists( 'mb_strtolower' ) ? mb_strtolower( $pathString ) : strtolower( $pathString ); 00340 $pathString = $contentImageSubtree . '/' . $pathString; 00341 } 00342 } 00343 else 00344 { 00345 $ini = eZINI::instance( 'image.ini' ); 00346 $contentImageSubtree = $ini->variable( 'FileSettings', 'VersionedImages' ); 00347 $pathString = $contentImageSubtree; 00348 $useVersion = true; 00349 } 00350 $attributeData = $this->originalAttributeData(); 00351 $attributeID = $attributeData['attribute_id']; 00352 $attributeVersion = $attributeData['attribute_version']; 00353 $attributeLanguage = $attributeData['attribute_language']; 00354 if ( $useVersion ) 00355 $identifierString = $attributeID . '/' . $attributeVersion . '-' . $attributeLanguage; 00356 else 00357 $identifierString = $attributeID . '-' . $attributeVersion . '-' . $attributeLanguage; 00358 $imagePath = eZSys::storageDirectory() . '/' . $pathString . '/' . $identifierString; 00359 return $imagePath; 00360 } 00361 00362 /*! 00363 \return The storage path for the image based on a node. 00364 00365 Similar to \a imagePath() but fetches name information from the node \a $mainNode. 00366 */ 00367 function imagePathByNode( $contentObjectAttribute, $mainNode ) 00368 { 00369 $pathString = $mainNode->pathWithNames(); 00370 $pathString = function_exists( 'mb_strtolower' ) ? mb_strtolower( $pathString ) : strtolower( $pathString ); 00371 00372 $ini = eZINI::instance( 'image.ini' ); 00373 $contentImageSubtree = $ini->variable( 'FileSettings', 'PublishedImages' ); 00374 $attributeData = $this->originalAttributeData(); 00375 $attributeID = $attributeData['attribute_id']; 00376 $attributeVersion = $attributeData['attribute_version']; 00377 $attributeLanguage = $attributeData['attribute_language']; 00378 $pathParts = array( eZSys::storageDirectory(), $contentImageSubtree ); 00379 if ( $pathString != '' ) 00380 { 00381 $pathParts[] = $pathString; 00382 } 00383 $pathParts[] = $attributeID . '-' . $attributeVersion . '-' . $attributeLanguage; 00384 $imagePath = implode( '/', $pathParts ); 00385 return $imagePath; 00386 } 00387 00388 /*! 00389 \return The image alias structure for the alias named \a $aliasName. 00390 00391 This will create the image alias if it does not exist yet, this can involve 00392 running image operations to for instance scale the image. 00393 */ 00394 function imageAlias( $aliasName ) 00395 { 00396 $imageManager = eZImageManager::factory(); 00397 if ( !$imageManager->hasAlias( $aliasName ) ) 00398 { 00399 return null; 00400 } 00401 00402 $aliasList = $this->aliasList(); 00403 if ( array_key_exists( $aliasName, $aliasList ) ) 00404 { 00405 return $aliasList[$aliasName]; 00406 } 00407 else 00408 { 00409 $original = $aliasList['original']; 00410 $basename = $original['basename']; 00411 if ( $imageManager->createImageAlias( $aliasName, $aliasList, 00412 array( 'basename' => $basename ) ) ) 00413 { 00414 $text = $this->displayText( $original['alternative_text'] ); 00415 $originalFilename = $original['original_filename']; 00416 foreach ( $aliasList as $aliasKey => $alias ) 00417 { 00418 $alias['original_filename'] = $originalFilename; 00419 $alias['text'] = $text; 00420 if ( $alias['url'] ) 00421 { 00422 $aliasFile = eZClusterFileHandler::instance( $alias['url'] ); 00423 if( $aliasFile->exists() ) 00424 $alias['filesize'] = $aliasFile->size(); 00425 } 00426 if ( $alias['is_new'] ) 00427 { 00428 eZImageFile::appendFilepath( $this->ContentObjectAttributeData['id'], $alias['url'] ); 00429 } 00430 $aliasList[$aliasKey] = $alias; 00431 } 00432 $this->setAliasList( $aliasList ); 00433 $this->addImageAliases( $aliasList ); 00434 $aliasList = $this->aliasList(); 00435 return $aliasList[$aliasName]; 00436 } 00437 } 00438 00439 return null; 00440 } 00441 00442 /*! 00443 Set alias list. Set alias list to current object 00444 00445 \param aliasList alias list 00446 */ 00447 protected function setAliasList( $aliasList ) 00448 { 00449 $this->ContentObjectAttributeData['DataTypeCustom']['alias_list'] = $aliasList; 00450 } 00451 00452 /* 00453 Set alias variation 00454 00455 \param alias name 00456 \param variation array 00457 */ 00458 protected function setAliasVariation( $aliasName, $variation ) 00459 { 00460 $this->ContentObjectAttributeData['DataTypeCustom']['alias_list'][$aliasName] = $variation; 00461 } 00462 00463 /*! 00464 Set alias value. 00465 00466 \param aliasName alias name 00467 \param attributeName attribute name 00468 \param value attribute value 00469 */ 00470 protected function setAliasAttribute( $aliasName, $attributeName, $value ) 00471 { 00472 $this->ContentObjectAttributeData['DataTypeCustom']['alias_list'][$aliasName][$attributeName] = $value; 00473 } 00474 00475 /*! 00476 \private 00477 \return A list of aliases structures for the current attribute.ezxml 00478 00479 The first this is called the XML data will be parsed into the internal 00480 structures. Subsequent calls will simply return the internal structure. 00481 */ 00482 function aliasList( $checkValidity = true ) 00483 { 00484 if ( $checkValidity && isset( $this->ContentObjectAttributeData['DataTypeCustom']['alias_list'] ) ) 00485 { 00486 return $this->ContentObjectAttributeData['DataTypeCustom']['alias_list']; 00487 } 00488 00489 eZDebug::accumulatorStart('imageparse', 'XML', 'Image XML parsing' ); 00490 00491 $domTree = new DOMDocument( '1.0', 'utf-8' ); 00492 00493 $xmlString = $this->ContentObjectAttributeData['data_text']; 00494 00495 $success = false; 00496 if ( $xmlString != '' ) 00497 { 00498 $success = $domTree->loadXML( $xmlString ); 00499 } 00500 00501 if ( !$success ) 00502 { 00503 $this->generateXMLData(); 00504 $xmlString = $this->ContentObjectAttributeData['data_text']; 00505 $success = $domTree->loadXML( $xmlString ); 00506 } 00507 00508 $this->ContentObjectAttributeData['DataTypeCustom']['dom_tree'] = $domTree; 00509 $imageNodeArray = $domTree->getElementsByTagName( "ezimage" ); 00510 00511 $aliasList = array(); 00512 00513 // I think this is a bug in the plain package or related to the bug I filed 00514 // about the image datatype serialization 00515 // http://ez.no/bugs/view/8821 ezpm Error: (eZFileHandler::copy) Unable to open source file in read mode 00516 if ( $imageNodeArray->length == 0 ) 00517 { 00518 return $aliasList; 00519 } 00520 00521 $imageNode = $imageNodeArray->item( 0 ); 00522 00523 $imageInfoNodeArray = $imageNode->getElementsByTagName( "information" ); 00524 $imageVariationNodeArray = $imageNode->getElementsByTagName( "alias" ); 00525 $imageOriginalArray = $imageNode->getElementsByTagName( "original" ); 00526 00527 $aliasEntry = array(); 00528 00529 $alternativeText = $imageNode->getAttribute( 'alternative_text' ); 00530 $originalFilename = $imageNode->getAttribute( 'original_filename' ); 00531 $basename = $imageNode->getAttribute( 'basename' ); 00532 $displayText = $this->displayText( $alternativeText ); 00533 00534 $originalData = array( 'attribute_id' => '', 00535 'attribute_version' => '', 00536 'attribute_language' => '' ); 00537 if ( $imageOriginalArray->length > 0 ) 00538 { 00539 $imageOriginalNode = $imageOriginalArray->item( 0 ); 00540 $originalData = array( 'attribute_id' => $imageOriginalNode->getAttribute( 'attribute_id' ), 00541 'attribute_version' => $imageOriginalNode->getAttribute( 'attribute_version' ), 00542 'attribute_language' => $imageOriginalNode->getAttribute( 'attribute_language' ) ); 00543 } 00544 if ( strlen( $originalData['attribute_id'] ) == 0 || 00545 strlen( $originalData['attribute_version'] ) == 0 || 00546 strlen( $originalData['attribute_language'] ) == 0 ) 00547 { 00548 $originalData = array( 'attribute_id' => $this->ContentObjectAttributeData['id'], 00549 'attribute_version' => $this->ContentObjectAttributeData['version'], 00550 'attribute_language' => $this->ContentObjectAttributeData['language_code'] ); 00551 } 00552 $this->setOriginalAttributeData( $originalData ); 00553 00554 $aliasEntry['name'] = 'original'; 00555 $aliasEntry['width'] = $imageNode->getAttribute( 'width' ); 00556 $aliasEntry['height'] = $imageNode->getAttribute( 'height' ); 00557 $aliasEntry['mime_type'] = $imageNode->getAttribute( 'mime_type' ); 00558 $aliasEntry['filename'] = $imageNode->getAttribute( 'filename' ); 00559 $aliasEntry['suffix'] = $imageNode->getAttribute( 'suffix' ); 00560 $aliasEntry['dirpath'] = $imageNode->getAttribute( 'dirpath' ); 00561 $aliasEntry['basename'] = $basename; 00562 $aliasEntry['alternative_text'] = $alternativeText; 00563 $aliasEntry['text'] = $displayText; 00564 $aliasEntry['original_filename'] = $originalFilename; 00565 $aliasEntry['url'] = $imageNode->getAttribute( 'url' ); 00566 $aliasEntry['alias_key'] = $imageNode->getAttribute( 'alias_key' ); 00567 $aliasEntry['timestamp'] = $imageNode->getAttribute( 'timestamp' ); 00568 $aliasEntry['full_path'] = $aliasEntry['url']; 00569 $aliasEntry['is_valid'] = $imageNode->getAttribute( 'is_valid' ); 00570 $aliasEntry['is_new'] = false; 00571 $aliasEntry['filesize'] = false; 00572 00573 if ( $aliasEntry['url'] ) 00574 { 00575 $aliasFile = eZClusterFileHandler::instance( $aliasEntry['url'] ); 00576 00577 if ( $aliasFile->exists() ) 00578 $aliasEntry['filesize'] = $aliasFile->size(); 00579 } 00580 00581 $imageInformation = false; 00582 if ( $imageInfoNodeArray->length > 0 ) 00583 { 00584 $imageInfoNode = $imageInfoNodeArray->item( 0 ); 00585 $imageInformation = $this->parseInformationNode( $imageInfoNode ); 00586 } 00587 $aliasEntry['info'] = $imageInformation; 00588 00589 $serialNumber = $imageNode->getAttribute( 'serial_number' ); 00590 if ( $serialNumber ) 00591 { 00592 $this->setImageSerialNumber( $serialNumber ); 00593 } 00594 00595 $aliasList['original'] = $aliasEntry; 00596 00597 if ( $imageVariationNodeArray->length > 0 ) 00598 { 00599 $imageManager = eZImageManager::factory(); 00600 foreach ( $imageVariationNodeArray as $imageVariation ) 00601 { 00602 $aliasEntry = array(); 00603 $aliasEntry['name'] = $imageVariation->getAttribute( 'name' ); 00604 $aliasEntry['width'] = $imageVariation->getAttribute( 'width' ); 00605 $aliasEntry['height'] = $imageVariation->getAttribute( 'height' ); 00606 $aliasEntry['mime_type'] = $imageVariation->getAttribute( 'mime_type' ); 00607 $aliasEntry['filename'] = $imageVariation->getAttribute( 'filename' ); 00608 $aliasEntry['suffix'] = $imageVariation->getAttribute( 'suffix' ); 00609 $aliasEntry['dirpath'] = $imageVariation->getAttribute( 'dirpath' ); 00610 $aliasEntry['alias_key'] = $imageVariation->getAttribute( 'alias_key' ); 00611 $aliasEntry['timestamp'] = $imageVariation->getAttribute( 'timestamp' ); 00612 $aliasEntry['is_valid'] = $imageVariation->getAttribute( 'is_valid' ); 00613 $aliasEntry['url'] = $imageVariation->getAttribute( 'url' ); 00614 $aliasEntry['basename'] = $basename; 00615 $aliasEntry['alternative_text'] = $alternativeText; 00616 $aliasEntry['text'] = $displayText; 00617 $aliasEntry['original_filename'] = $originalFilename; 00618 $aliasEntry['full_path'] = $aliasEntry['url']; 00619 $aliasEntry['is_new'] = false; 00620 $aliasEntry['info'] = $imageInformation; 00621 00622 if ( $aliasEntry['url'] ) 00623 { 00624 $aliasFile = eZClusterFileHandler::instance( $aliasEntry['url'] ); 00625 00626 if ( $aliasFile->exists() ) 00627 $aliasEntry['filesize'] = $aliasFile->size(); 00628 } 00629 00630 if ( $imageManager->isImageAliasValid( $aliasEntry ) || !$checkValidity ) 00631 { 00632 $aliasList[$aliasEntry['name']] = $aliasEntry; 00633 } 00634 } 00635 } 00636 if ( $checkValidity ) 00637 $this->setAliasList( $aliasList ); 00638 eZDebug::accumulatorStop( 'imageparse' ); 00639 return $aliasList; 00640 } 00641 00642 /** 00643 * Removes all image alias files which the attribute refers to. 00644 * 00645 * @param eZContentObjectAttribute 00646 * @note If you want to remove the alias information use removeAliases(). 00647 */ 00648 static function removeAllAliases( $contentObjectAttribute ) 00649 { 00650 $handler = $contentObjectAttribute->attribute( 'content' ); 00651 if ( !$handler->isImageOwner() ) 00652 { 00653 return; 00654 } 00655 $attributeData = $handler->originalAttributeData(); 00656 $files = eZImageFile::fetchForContentObjectAttribute( $attributeData['attribute_id'], false ); 00657 $dirs = array(); 00658 00659 foreach ( $files as $filepath ) 00660 { 00661 $file = eZClusterFileHandler::instance( $filepath ); 00662 if ( $file->exists() ) 00663 { 00664 $file->fileDelete( $filepath ); 00665 $dirs[] = eZDir::dirpath( $filepath ); 00666 } 00667 } 00668 $dirs = array_unique( $dirs ); 00669 foreach ( $dirs as $dirpath ) 00670 { 00671 eZDir::cleanupEmptyDirectories( $dirpath ); 00672 } 00673 eZImageFile::removeForContentObjectAttribute( $attributeData['attribute_id'] ); 00674 } 00675 00676 /** 00677 * Removes the images alias while keeping the original image. 00678 * @see eZCache::purgeAllAliases() 00679 * 00680 * @param eZContentObjectAttribute $contentObjectAttribute 00681 */ 00682 public function purgeAllAliases( eZContentObjectAttribute $contentObjectAttribute ) 00683 { 00684 $aliasList = $this->aliasList( false ); 00685 unset( $aliasList['original'] ); // keeping original 00686 00687 foreach ( $aliasList as $aliasName => $alias ) 00688 { 00689 $filepath = $alias['url']; 00690 00691 $file = eZClusterFileHandler::instance( $filepath ); 00692 if ( $file->exists() ) 00693 { 00694 $file->purge(); 00695 eZImageFile::removeFilepath( $this->ContentObjectAttributeData['id'], $filepath ); 00696 eZDir::cleanupEmptyDirectories( $alias['dirpath'] ); 00697 } 00698 else 00699 { 00700 eZDebug::writeError( "Image file $filepath for alias $aliasName does not exist, could not remove from disk", __METHOD__ ); 00701 } 00702 } 00703 00704 $doc = $this->ContentObjectAttributeData['DataTypeCustom']['dom_tree']; 00705 foreach ( $doc->getElementsByTagName( 'alias' ) as $aliasNode ) 00706 { 00707 $aliasNode->parentNode->removeChild( $aliasNode ); 00708 } 00709 $this->ContentObjectAttributeData['DataTypeCustom']['dom_tree'] = $doc; 00710 unset( $this->ContentObjectAttributeData['DataTypeCustom']['alias_list'] ); 00711 00712 $this->storeDOMTree( $doc, true, $contentObjectAttribute ); 00713 } 00714 00715 /** 00716 * Removes all the image aliases and their information. 00717 * The stored images will also be removed if the attribute is the owner 00718 * of the images. 00719 * 00720 * After the images are removed the attribute will containe an internal 00721 * structure with empty data 00722 * 00723 * @param eZContentObjectAttribute $contentObjectAttribute 00724 * Content object attribute to remove aliases for 00725 * 00726 * @return void 00727 */ 00728 function removeAliases( $contentObjectAttribute ) 00729 { 00730 $aliasList = $this->aliasList(); 00731 $alternativeText = false; 00732 00733 $contentObjectAttributeVersion = $this->ContentObjectAttributeData['version']; 00734 $contentObjectAttributeID = $this->ContentObjectAttributeData['id']; 00735 00736 $isImageOwner = $this->isImageOwner(); 00737 00738 // We loop over each image alias, and look up the file in ezcontentobject_attribute 00739 // Only images referenced by one version will be removed 00740 foreach ( $aliasList as $aliasName => $alias ) 00741 { 00742 $dirpath = $alias['dirpath']; 00743 $doNotDelete = false; // Do not delete files from storage 00744 00745 if ( $aliasName == 'original' ) 00746 $alternativeText = $alias['alternative_text']; 00747 if ( $alias['is_valid'] ) 00748 { 00749 $filepath = $alias['url']; 00750 00751 // Fetch ezimage attributes that use $filepath 00752 // Always returns current attribute (array of $contentObjectAttributeID and $contentObjectAttributeVersion) 00753 $dbResult = eZImageFile::fetchImageAttributesByFilepath( $filepath, $contentObjectAttributeID ); 00754 $dbResultCount = count( $dbResult ); 00755 // Check if there are the attributes. 00756 if ( $dbResultCount > 0 ) 00757 { 00758 $doNotDelete = true; 00759 foreach ( $dbResult as $res ) 00760 { 00761 // We only look results where the version matches 00762 if ( $res['version'] == $contentObjectAttributeVersion ) 00763 { 00764 // If more than one result has been returned, it means 00765 // that another version is using the same image, 00766 // and we should not delete this file 00767 if ( $dbResultCount > 1 ) 00768 { 00769 continue; 00770 } 00771 // Only one result means that the current attribute 00772 // & version are the only ones using this image, 00773 // and it can be removed 00774 else 00775 { 00776 $doNotDelete = false; 00777 } 00778 } 00779 00780 eZImageFile::appendFilepath( $res['id'], $filepath, true ); 00781 } 00782 } 00783 00784 if ( !$doNotDelete ) 00785 { 00786 $file = eZClusterFileHandler::instance( $filepath ); 00787 if ( $file->exists() ) 00788 { 00789 $file->delete(); 00790 eZImageFile::removeFilepath( $contentObjectAttributeID, $filepath ); 00791 eZDir::cleanupEmptyDirectories( $dirpath ); 00792 } 00793 else 00794 { 00795 eZDebug::writeError( "Image file $filepath for alias $aliasName does not exist, could not remove from disk", __METHOD__ ); 00796 } 00797 } 00798 } 00799 } 00800 00801 $doc = new DOMDocument( '1.0', 'utf-8' ); 00802 $imageNode = $doc->createElement( "ezimage" ); 00803 $doc->appendChild( $imageNode ); 00804 00805 $imageNode->setAttribute( 'serial_number', false ); 00806 $imageNode->setAttribute( 'is_valid', false ); 00807 $imageNode->setAttribute( 'filename', false ); 00808 $imageNode->setAttribute( 'suffix', false ); 00809 $imageNode->setAttribute( 'basename', false ); 00810 $imageNode->setAttribute( 'dirpath', false ); 00811 $imageNode->setAttribute( 'url', false ); 00812 $imageNode->setAttribute( 'original_filename', false ); 00813 $imageNode->setAttribute( 'mime_type', false ); 00814 $imageNode->setAttribute( 'width', false ); 00815 $imageNode->setAttribute( 'height', false ); 00816 $imageNode->setAttribute( 'alternative_text', $alternativeText ); 00817 $imageNode->setAttribute( 'alias_key', false ); 00818 $imageNode->setAttribute( 'timestamp', false ); 00819 00820 $this->ContentObjectAttributeData['DataTypeCustom']['dom_tree'] = $doc; 00821 unset( $this->ContentObjectAttributeData['DataTypeCustom']['alias_list'] ); 00822 00823 $this->storeDOMTree( $doc, true, $contentObjectAttribute ); 00824 } 00825 00826 /*! 00827 Will update the path for images to point to the new path \a $dirpath and filename \a $name. 00828 00829 This is usually called when the object contain the image attribute is moved in the tree. 00830 */ 00831 function updateAliasPath( $dirpath, $name ) 00832 { 00833 if ( !file_exists( $dirpath ) ) 00834 { 00835 eZDir::mkdir( $dirpath, false, true ); 00836 } 00837 $aliasList = $this->aliasList(); 00838 $this->resetImageSerialNumber(); 00839 00840 foreach ( $aliasList as $aliasName => $alias ) 00841 { 00842 if ( $alias['dirpath'] != $dirpath ) 00843 { 00844 $oldDirpath = $alias['url']; 00845 $oldURL = $alias['url']; 00846 $basename = $name; 00847 if ( $aliasName != 'original' ) 00848 $basename .= '_' . $aliasName; 00849 eZMimeType::changeFileData( $alias, $dirpath, $basename ); 00850 $alias['full_path'] = $alias['url']; 00851 if ( $this->isImageOwner() ) 00852 { 00853 if ( $oldURL == '' ) 00854 { 00855 continue; 00856 } 00857 00858 $fileHandler = eZClusterFileHandler::instance(); 00859 $fileHandler->fileMove( $oldURL, $alias['url'] ); 00860 00861 eZDir::cleanupEmptyDirectories( $oldDirpath ); 00862 eZImageFile::moveFilepath( $this->ContentObjectAttributeData['id'], $oldURL, $alias['url'] ); 00863 } 00864 else 00865 { 00866 $fileHandler = eZClusterFileHandler::instance(); 00867 $fileHandler->fileLinkCopy( $oldURL, $alias['url'], false ); 00868 eZImageFile::appendFilepath( $this->ContentObjectAttributeData['id'], $alias['url'] ); 00869 } 00870 $this->setAliasVariation( $aliasName, $alias ); 00871 } 00872 } 00873 00874 $this->recreateDOMTree(); 00875 $this->setStorageRequired(); 00876 } 00877 00878 /*! 00879 \private 00880 Creates XML attributes containing information on the original image attribute. 00881 00882 The new attributes will be appended to \a $originalNode. 00883 */ 00884 function createOriginalAttributeXMLData( $originalNode, $originalData ) 00885 { 00886 $originalNode->setAttribute( 'attribute_id', $originalData['attribute_id'] ); 00887 $originalNode->setAttribute( 'attribute_version', $originalData['attribute_version'] ); 00888 $originalNode->setAttribute( 'attribute_language', $originalData['attribute_language'] ); 00889 } 00890 00891 /*! 00892 \private 00893 Recreates the DOM tree from the internal array structures and stores the DOM tree 00894 in the 'data_text' field of the attribute. 00895 */ 00896 function recreateDOMTree() 00897 { 00898 $aliasList = $this->aliasList(); 00899 $doc = new DOMDocument( '1.0', 'utf-8' ); 00900 $imageNode = $doc->createElement( "ezimage" ); 00901 $doc->appendChild( $imageNode ); 00902 00903 $originalNode = $doc->createElement( "original" ); 00904 $imageNode->appendChild( $originalNode ); 00905 00906 $imageManager = eZImageManager::factory(); 00907 00908 $aliasName = 'original'; 00909 00910 $originalData = $this->originalAttributeData(); 00911 $this->createOriginalAttributeXMLData( $originalNode, $originalData ); 00912 00913 $imageNode->setAttribute( 'serial_number', $this->imageSerialNumber() ); 00914 $imageNode->setAttribute( 'is_valid', $aliasList[$aliasName]['is_valid'] ); 00915 $imageNode->setAttribute( 'filename', $aliasList[$aliasName]['filename'] ); 00916 $imageNode->setAttribute( 'suffix', $aliasList[$aliasName]['suffix'] ); 00917 $imageNode->setAttribute( 'basename', $aliasList[$aliasName]['basename'] ); 00918 $imageNode->setAttribute( 'dirpath', $aliasList[$aliasName]['dirpath'] ); 00919 $imageNode->setAttribute( 'url', $aliasList[$aliasName]['url'] ); 00920 $imageNode->setAttribute( 'original_filename', $aliasList[$aliasName]['original_filename'] ); 00921 $imageNode->setAttribute( 'mime_type', $aliasList[$aliasName]['mime_type'] ); 00922 $imageNode->setAttribute( 'width', $aliasList[$aliasName]['width'] ); 00923 $imageNode->setAttribute( 'height', $aliasList[$aliasName]['height'] ); 00924 $imageNode->setAttribute( 'alternative_text', $aliasList[$aliasName]['alternative_text'] ); 00925 $imageNode->setAttribute( 'alias_key', $imageManager->createImageAliasKey( $imageManager->alias( $aliasName ) ) ); 00926 $imageNode->setAttribute( 'timestamp', $aliasList[$aliasName]['timestamp'] ); 00927 00928 $filename = $aliasList[$aliasName]['url']; 00929 if ( $filename ) 00930 { 00931 $imageFile = eZClusterFileHandler::instance( $filename ); 00932 00933 $fetchedFilePath = $imageFile->fetchUnique(); 00934 00935 //(Cluster) Get mime data of real file, and fetch info by image analizer. 00936 $mimeDataTemp = eZMimeType::findByFileContents( $fetchedFilePath ); 00937 $imageManager->analyzeImage( $mimeDataTemp ); 00938 00939 //(Cluster) Get mime data of a file which does not really exist on file system. We need this to build correct imageInformationNode. 00940 $mimeData = eZMimeType::findByURL( $filename ); 00941 if ( isset( $mimeDataTemp['info'] ) ) 00942 $mimeData['info'] = $mimeDataTemp['info']; 00943 00944 $this->createImageInformationNode( $imageNode, $mimeData ); 00945 $imageFile->fileDeleteLocal( $fetchedFilePath ); 00946 } 00947 00948 foreach ( $aliasList as $aliasName => $alias ) 00949 { 00950 if ( $aliasName == 'original' ) 00951 continue; 00952 $this->addImageAliasToXML( $doc, $alias ); 00953 } 00954 00955 $this->setDOMTree( $doc ); 00956 } 00957 00958 /*! 00959 \return the DOM tree for the current content object attribute. 00960 \note It will cache the result in the DataTypeCustom member variable of the 00961 content object attribute in the 'dom_tree' key. 00962 */ 00963 function domTree() 00964 { 00965 $contentObjectAttributeData = $this->ContentObjectAttributeData; 00966 if ( isset( $contentObjectAttributeData['DataTypeCustom']['dom_tree'] ) ) 00967 { 00968 return $contentObjectAttributeData['DataTypeCustom']['dom_tree']; 00969 } 00970 00971 $dom = new DOMDocument( '1.0', 'utf-8' ); 00972 $xmlString = $contentObjectAttributeData['data_text']; 00973 $success = $xmlString == '' ? false : $dom->loadXML( $xmlString ); 00974 if ( !$success ) 00975 { 00976 $this->generateXMLData(); 00977 $xmlString = $this->ContentObjectAttributeData['data_text']; 00978 $success = $dom->loadXML( $xmlString ); 00979 } 00980 00981 $contentObjectAttributeData['DataTypeCustom']['dom_tree'] = $dom; 00982 00983 return $dom; 00984 } 00985 00986 /*! 00987 \private 00988 Parses the information node and generates the internal information structures. 00989 00990 The information node contains information from the image itself, for instance 00991 EXIF data from a JPEG or TIFF image. 00992 00993 \param $imageInfoNode 00994 00995 \return $imageInformation array 00996 */ 00997 function parseInformationNode( $imageInfoNode ) 00998 { 00999 $imageInformation = array(); 01000 01001 $attributes = $imageInfoNode->attributes; 01002 foreach ( $attributes as $attribute ) 01003 { 01004 $imageInformation[$attribute->name] = $attribute->value; 01005 } 01006 01007 $children = $imageInfoNode->childNodes; 01008 foreach ( $children as $child ) 01009 { 01010 if ( $child->nodeType != XML_ELEMENT_NODE ) 01011 { 01012 continue; 01013 } 01014 01015 $childName = false; 01016 if ( isset ( $child->localName ) ) 01017 { 01018 $childName = $child->localName; 01019 } 01020 01021 if ( $childName == 'array' ) 01022 { 01023 $name = $child->getAttribute( 'name' ); 01024 $items = $child->getElementsByTagName( 'item' ); 01025 $array = array(); 01026 foreach ( $items as $item ) 01027 { 01028 $itemValue = $item->textContent; 01029 if ( $item->getAttribute( 'base64' ) == '1' ) 01030 { 01031 $array[$item->getAttribute( 'key' )] = base64_decode( $itemValue ); 01032 } 01033 else 01034 { 01035 $array[$item->getAttribute( 'key' )] = $itemValue; 01036 } 01037 } 01038 ksort( $array ); 01039 $imageInformation[$name] = $array; 01040 } 01041 else if ( $childName == 'serialized' ) 01042 { 01043 $name = $child->getAttribute( 'name' ); 01044 $data = $child->getAttribute( 'data' ); 01045 $imageInformation[$name] = unserialize( $data ); 01046 } 01047 } 01048 01049 return $imageInformation; 01050 } 01051 01052 /*! 01053 \static 01054 Normalized the image name \a $imageName by removing all characters that are not considered 01055 filename or URL friendly. 01056 The filename will also be in non-capital letters. 01057 */ 01058 function normalizeImageName( $imageName ) 01059 { 01060 // Initialize transformation system 01061 $trans = eZCharTransform::instance(); 01062 01063 $imageName = eZURLAliasML::convertToAlias( $imageName ); 01064 return $imageName; 01065 } 01066 01067 /** 01068 * Sets the uploaded HTTP file object to $httpFile. 01069 * 01070 * This object is used to store information about the image file until the 01071 * content object attribute is to be stored. 01072 * 01073 * @param mixed $httpFile 01074 * 01075 * @see httpFile 01076 */ 01077 function setHTTPFile( $httpFile ) 01078 { 01079 $this->ContentObjectAttributeData['DataTypeCustom']['http_file'] = $httpFile; 01080 } 01081 01082 /** 01083 * Returns the stored HTTP file object or false if no object is stored. 01084 * 01085 * @param bool $release Erase the content of the stored HTTP file 01086 * 01087 * @see setHTTPFile 01088 */ 01089 function httpFile( $release = false ) 01090 { 01091 if ( isset( $this->ContentObjectAttributeData['DataTypeCustom']['http_file'] ) ) 01092 { 01093 $httpFile = $this->ContentObjectAttributeData['DataTypeCustom']['http_file']; 01094 if ( $release ) 01095 { 01096 unset( $this->ContentObjectAttributeData['DataTypeCustom']['http_file'] ); 01097 } 01098 return $httpFile; 01099 } 01100 01101 return false; 01102 } 01103 01104 /** 01105 * Initializes the content object attribute with the uploaded HTTP file 01106 * 01107 * @param eZHTTPFile $httpFile 01108 * @param string $imageAltText Optional image ALT text 01109 * 01110 * @return TODO: FIXME 01111 */ 01112 function initializeFromHTTPFile( $httpFile, $imageAltText = false ) 01113 { 01114 $this->increaseImageSerialNumber(); 01115 01116 $mimeData = eZMimeType::findByFileContents( $httpFile->attribute( 'filename' ) ); 01117 if ( !$mimeData['is_valid'] ) 01118 { 01119 $mimeData = eZMimeType::findByName( $httpFile->attribute( 'mime_type' ) ); 01120 if ( !$mimeData['is_valid'] ) 01121 { 01122 $mimeData = eZMimeType::findByURL( $httpFile->attribute( 'original_filename' ) ); 01123 } 01124 } 01125 $attr = false; 01126 $this->removeAliases( $attr ); 01127 $this->setOriginalAttributeDataValues( $this->ContentObjectAttributeData['id'], 01128 $this->ContentObjectAttributeData['version'], 01129 $this->ContentObjectAttributeData['language_code'] ); 01130 $contentVersion = eZContentObjectVersion::fetchVersion( $this->ContentObjectAttributeData['version'], 01131 $this->ContentObjectAttributeData['contentobject_id'] ); 01132 $objectName = $this->imageName( $this->ContentObjectAttributeData, $contentVersion ); 01133 $objectPathString = $this->imagePath( $this->ContentObjectAttributeData, $contentVersion, true ); 01134 01135 eZMimeType::changeBaseName( $mimeData, $objectName ); 01136 eZMimeType::changeDirectoryPath( $mimeData, $objectPathString ); 01137 01138 $httpFile->store( false, false, $mimeData ); 01139 01140 $originalFilename = $httpFile->attribute( 'original_filename' ); 01141 return $this->initialize( $mimeData, $originalFilename, $imageAltText ); 01142 } 01143 01144 /*! 01145 Initializes the content object attribute \a $contentObjectAttribute with the filename \a $filename. 01146 Optionally you may also specify the alternative text in the parameter \a $imageAltText. 01147 \sa initialize 01148 */ 01149 function initializeFromFile( $filename, $imageAltText = false, $originalFilename = false ) 01150 { 01151 if ( !file_exists( $filename ) ) 01152 { 01153 $contentObjectID = isset( $this->ContentObjectAttributeData['contentobject_id'] ) ? $this->ContentObjectAttributeData['contentobject_id'] : 0; 01154 $contentObjectAttributeID = isset( $this->ContentObjectAttributeData['id'] ) ? $this->ContentObjectAttributeData['id'] : 0; 01155 $version = isset( $this->ContentObjectAttributeData['version'] ) ? $this->ContentObjectAttributeData['version'] : 0; 01156 $contentObject = eZContentObject::fetch( $contentObjectID ); 01157 $contentObjectAttribute = eZContentObjectAttribute::fetch( $contentObjectAttributeID, $version ); 01158 $contentObjectAttributeName = ''; 01159 $contentObjectName = ''; 01160 01161 if ( $contentObject instanceof eZContentObject ) 01162 $contentObjectName = $contentObject->attribute('name'); 01163 01164 if ( $contentObjectAttribute instanceof eZContentObjectAttribute ) 01165 $contentObjectAttributeName = $contentObjectAttribute->attribute( 'contentclass_attribute_name' ); 01166 01167 eZDebug::writeError( "The image '$filename' does not exist, cannot initialize image attribute: '$contentObjectAttributeName' (id: $contentObjectAttributeID) for content object: '$contentObjectName' (id: $contentObjectID)", __METHOD__ ); 01168 return false; 01169 } 01170 01171 $this->increaseImageSerialNumber(); 01172 01173 if ( !$originalFilename ) 01174 $originalFilename = basename( $filename ); 01175 $mimeData = eZMimeType::findByFileContents( $filename ); 01176 if ( !$mimeData['is_valid'] and 01177 $originalFilename != $filename ) 01178 { 01179 $mimeData = eZMimeType::findByFileContents( $originalFilename ); 01180 } 01181 01182 $attr = false; 01183 $this->removeAliases( $attr ); 01184 $this->setOriginalAttributeDataValues( $this->ContentObjectAttributeData['id'], 01185 $this->ContentObjectAttributeData['version'], 01186 $this->ContentObjectAttributeData['language_code'] ); 01187 $contentVersion = eZContentObjectVersion::fetchVersion( $this->ContentObjectAttributeData['version'], 01188 $this->ContentObjectAttributeData['contentobject_id'] ); 01189 $objectName = $this->imageName( $this->ContentObjectAttributeData, $contentVersion ); 01190 $objectPathString = $this->imagePath( $this->ContentObjectAttributeData, $contentVersion, true ); 01191 01192 eZMimeType::changeBaseName( $mimeData, $objectName ); 01193 eZMimeType::changeDirectoryPath( $mimeData, $objectPathString ); 01194 if ( !file_exists( $mimeData['dirpath'] ) ) 01195 { 01196 eZDir::mkdir( $mimeData['dirpath'], false, true ); 01197 } 01198 01199 eZFileHandler::copy( $filename, $mimeData['url'] ); 01200 01201 return $this->initialize( $mimeData, $originalFilename, $imageAltText ); 01202 } 01203 01204 /*! 01205 Makes sure the attribute contains the image file mentioned in \a $mimeData. 01206 This involves removing any previous image (and image aliases), increasing 01207 the image name counter, figuring out the image size and creating 01208 the internal XML structure. 01209 \return \c true on success. 01210 */ 01211 function initialize( $mimeData, $originalFilename, $imageAltText = false ) 01212 { 01213 $imageManager = eZImageManager::factory(); 01214 01215 $this->setOriginalAttributeDataValues( $this->ContentObjectAttributeData['id'], 01216 $this->ContentObjectAttributeData['version'], 01217 $this->ContentObjectAttributeData['language_code'] ); 01218 01219 $aliasList = array( 'original' => $mimeData ); 01220 $aliasList['original']['alternative_text'] = $imageAltText; 01221 $aliasList['original']['original_filename'] = $originalFilename; 01222 01223 $fileHandler = eZClusterFileHandler::instance(); 01224 $filePath = $mimeData['url']; 01225 $fileHandler->fileStore( $filePath, 'image', false, $mimeData['name'] ); 01226 01227 if ( $imageManager->createImageAlias( 'original', $aliasList, array( 'basename' => $mimeData['basename'] ) ) ) 01228 { 01229 $mimeData = $aliasList['original']; 01230 $mimeData['name'] = $mimeData['mime_type']; 01231 $aliasList['original']['original_filename'] = $originalFilename; 01232 } 01233 01234 if ( $aliasList['original']['url'] ) 01235 { 01236 $aliasFile = eZClusterFileHandler::instance( $aliasList['original']['url'] ); 01237 if( $aliasFile->exists() ) 01238 $aliasList['original']['filesize'] = $aliasFile->size(); 01239 } 01240 01241 // refetch the original image 01242 $fileHandler->fileFetch( $filePath ); 01243 01244 $imageManager->analyzeImage( $mimeData ); 01245 01246 $doc = new DOMDocument( '1.0', 'utf-8' ); 01247 $imageNode = $doc->createElement( "ezimage" ); 01248 $doc->appendChild( $imageNode ); 01249 01250 $width = false; 01251 $height = false; 01252 $info = getimagesize( $mimeData['url'] ); 01253 if ( $info ) 01254 { 01255 $width = $info[0]; 01256 $height = $info[1]; 01257 } 01258 01259 $originalNode = $doc->createElement( "original" ); 01260 $imageNode->appendChild( $originalNode ); 01261 $attributeData = $this->originalAttributeData(); 01262 $this->createOriginalAttributeXMLData( $originalNode, $attributeData ); 01263 01264 $imageNode->setAttribute( 'serial_number', $this->imageSerialNumber() ); 01265 $imageNode->setAttribute( 'is_valid', true ); 01266 $imageNode->setAttribute( 'filename', $mimeData['filename'] ); 01267 $imageNode->setAttribute( 'suffix', $mimeData['suffix'] ); 01268 $imageNode->setAttribute( 'basename', $mimeData['basename'] ); 01269 $imageNode->setAttribute( 'dirpath', $mimeData['dirpath'] ); 01270 $imageNode->setAttribute( 'url', $mimeData['url'] ); 01271 $imageNode->setAttribute( 'original_filename', $originalFilename ); 01272 $imageNode->setAttribute( 'mime_type', $mimeData['name'] ); 01273 $imageNode->setAttribute( 'width', $width ); 01274 $imageNode->setAttribute( 'height', $height ); 01275 $imageNode->setAttribute( 'alternative_text', $imageAltText ); 01276 $imageNode->setAttribute( 'alias_key', $imageManager->createImageAliasKey( $imageManager->alias( 'original' ) ) ); 01277 $imageNode->setAttribute( 'timestamp', time() ); 01278 01279 $this->createImageInformationNode( $imageNode, $mimeData ); 01280 01281 $this->setDOMTree( $doc ); 01282 01283 $this->setAliasList( $aliasList ); 01284 01285 eZImageFile::appendFilepath( $this->ContentObjectAttributeData['id'], $mimeData['url'] ); 01286 01287 $fileHandler->fileDeleteLocal( $filePath ); 01288 01289 return true; 01290 } 01291 01292 function createImageInformationNode( $imageNode, $mimeData ) 01293 { 01294 $dom = $imageNode->ownerDocument; 01295 if ( isset( $mimeData['info'] ) and 01296 $mimeData['info'] ) 01297 { 01298 $imageInfoNode = $dom->createElement( 'information' ); 01299 $info = $mimeData['info']; 01300 foreach ( $info as $infoItemName => $infoItem ) 01301 { 01302 if ( is_array( $infoItem ) ) 01303 { 01304 $hasScalarValues = true; 01305 foreach ( $infoItem as $infoArrayItem ) 01306 { 01307 if ( is_array( $infoArrayItem ) ) 01308 { 01309 $hasScalarValues = false; 01310 break; 01311 } 01312 } 01313 if ( !$hasScalarValues ) 01314 { 01315 $toRemove = array(); 01316 foreach ( $infoItem as $key => $value ) 01317 { 01318 if ( is_string( $value ) && !ctype_print( $value ) ) 01319 { 01320 $toRemove[] = $key; 01321 } 01322 } 01323 01324 if ( count( $toRemove ) > 0 ) 01325 { 01326 eZDebug::writeDebug( 'removing image information items containing non-printable characters: ' . implode( ', ', $toRemove ) ); 01327 01328 foreach ( $toRemove as $remove ) 01329 { 01330 unset( $infoItem[$remove] ); 01331 } 01332 } 01333 01334 unset( $serializedNode ); 01335 $serializedNode = $dom->createElement( 'serialized' ); 01336 $serializedNode->setAttribute( 'name', $infoItemName ); 01337 $serializedNode->setAttribute( 'data', serialize( $infoItem ) ); 01338 01339 $imageInfoNode->appendChild( $serializedNode ); 01340 } 01341 else 01342 { 01343 unset( $arrayNode ); 01344 $arrayNode = $dom->createElement( 'array' ); 01345 $arrayNode->setAttribute( 'name', $infoItemName ); 01346 01347 $imageInfoNode->appendChild( $arrayNode ); 01348 foreach ( $infoItem as $infoArrayKey => $infoArrayItem ) 01349 { 01350 unset( $arrayItemNode ); 01351 $arrayItemNode = $dom->createElement( 'item' ); 01352 $arrayItemNode->appendChild( $dom->createTextNode( base64_encode( $infoArrayItem ) ) ); 01353 $arrayItemNode->setAttribute( 'key', $infoArrayKey ); 01354 $arrayItemNode->setAttribute( 'base64', 1 ); 01355 01356 $arrayNode->appendChild( $arrayItemNode ); 01357 } 01358 } 01359 } 01360 else 01361 { 01362 $infoItem = iconv( mb_detect_encoding( $infoItem ), 'UTF-8//IGNORE', $infoItem ); 01363 $imageInfoNode->setAttribute( $infoItemName, $infoItem ); 01364 } 01365 } 01366 $imageNode->appendChild( $imageInfoNode ); 01367 } 01368 } 01369 01370 /*! 01371 Adds all the new image alias structures in \a $imageAliasList to the content object attribute. 01372 */ 01373 function addImageAliases( $imageAliasList ) 01374 { 01375 $domTree = $this->domTree(); 01376 foreach ( $imageAliasList as $imageAliasName => $imageAlias ) 01377 { 01378 if ( $imageAlias['is_new'] ) 01379 { 01380 $this->addImageAliasToXML( $domTree, $imageAlias ); 01381 $this->setAliasAttribute( $imageAliasName, 'is_new', false ); 01382 } 01383 } 01384 $attr = false; 01385 $this->storeDOMTree( $domTree, true, $attr ); 01386 } 01387 01388 /*! 01389 Adds the image alias structure \a $imageAlias to the content object attribute. 01390 */ 01391 function addImageAlias( $imageAlias ) 01392 { 01393 $domTree = $this->domTree(); 01394 $this->addImageAliasToXML( $domTree, $imageAlias ); 01395 $attr = false; 01396 $this->storeDOMTree( $domTree, true, $attr ); 01397 01398 } 01399 01400 /*! 01401 Adds the image alias structure \a $imageAlias to the XML DOM document \a $domTree. 01402 */ 01403 function addImageAliasToXML( $domTree, $imageAlias ) 01404 { 01405 $imageVariationNodeArray = $domTree->getElementsByTagName( 'alias' ); 01406 $imageNode = false; 01407 foreach ( $imageVariationNodeArray as $imageVariation ) 01408 { 01409 $aliasEntryName = $imageVariation->getAttribute( 'name' ); 01410 if ( $aliasEntryName == $imageAlias['name'] ) 01411 { 01412 $imageNode = $imageVariation; 01413 break; 01414 } 01415 } 01416 if ( !$imageNode ) 01417 { 01418 $rootNode = $domTree->documentElement; 01419 01420 $imageNode = $domTree->createElement( "alias" ); 01421 $rootNode->appendChild( $imageNode ); 01422 } 01423 else 01424 { 01425 $imageNode->removeAttribute( 'name' ); 01426 $imageNode->removeAttribute( 'filename' ); 01427 $imageNode->removeAttribute( 'suffix' ); 01428 $imageNode->removeAttribute( 'dirpath' ); 01429 $imageNode->removeAttribute( 'url' ); 01430 $imageNode->removeAttribute( 'mime_type' ); 01431 $imageNode->removeAttribute( 'width' ); 01432 $imageNode->removeAttribute( 'height' ); 01433 $imageNode->removeAttribute( 'alias_key' ); 01434 $imageNode->removeAttribute( 'timestamp' ); 01435 $imageNode->removeAttribute( 'is_valid' ); 01436 } 01437 $imageNode->setAttribute( 'name', $imageAlias['name'] ); 01438 $imageNode->setAttribute( 'filename', $imageAlias['filename'] ); 01439 $imageNode->setAttribute( 'suffix', $imageAlias['suffix'] ); 01440 $imageNode->setAttribute( 'dirpath', $imageAlias['dirpath'] ); 01441 $imageNode->setAttribute( 'url', $imageAlias['url'] ); 01442 $imageNode->setAttribute( 'mime_type', $imageAlias['mime_type'] ); 01443 $imageNode->setAttribute( 'width', $imageAlias['width'] ); 01444 $imageNode->setAttribute( 'height', $imageAlias['height'] ); 01445 $imageNode->setAttribute( 'alias_key', $imageAlias['alias_key'] ); 01446 $imageNode->setAttribute( 'timestamp', $imageAlias['timestamp'] ); 01447 $imageNode->setAttribute( 'is_valid', $imageAlias['is_valid'] ); 01448 } 01449 01450 /*! 01451 Sets the XML DOM document \a $domTree as the current DOM document. 01452 */ 01453 function setDOMTree( $domTree ) 01454 { 01455 $this->ContentObjectAttributeData['DataTypeCustom']['dom_tree'] = $domTree; 01456 $this->ContentObjectAttributeData['DataTypeCustom']['is_storage_required'] = true; 01457 } 01458 01459 /*! 01460 Stores the XML DOM document \a $domTree to the content object attribute. 01461 */ 01462 function storeDOMTree( $domTree, $storeAttribute, $contentObjectAttributeRef ) 01463 { 01464 if ( !$domTree ) 01465 return false; 01466 $this->ContentObjectAttributeData['DataTypeCustom']['dom_tree'] = $domTree; 01467 $this->ContentObjectAttributeData['DataTypeCustom']['is_storage_required'] = false; 01468 $xmlString = $domTree->saveXML(); 01469 $this->ContentObjectAttributeData['data_text'] = $xmlString; 01470 01471 if ( $storeAttribute ) 01472 { 01473 if ( is_object( $contentObjectAttributeRef ) ) 01474 { 01475 $contentObjectAttribute = $contentObjectAttributeRef; 01476 } 01477 else 01478 { 01479 $contentObjectAttribute = eZContentObjectAttribute::fetch( $this->ContentObjectAttributeData['id'], 01480 $this->ContentObjectAttributeData['version'] ); 01481 } 01482 01483 if ( is_object( $contentObjectAttribute ) ) 01484 { 01485 $contentObjectAttribute->setAttribute( 'data_text', $xmlString ); 01486 $contentObjectAttribute->storeData(); 01487 } 01488 else 01489 { 01490 eZDebug::writeError( "Invalid objectAttribute: id = " . $this->ContentObjectAttributeData['id'] . 01491 " version = " . $this->ContentObjectAttributeData['version'] , 01492 __METHOD__ ); 01493 } 01494 } 01495 01496 return true; 01497 } 01498 01499 /*! 01500 Stores the data in the image alias handler to the content object attribute. 01501 \sa isStorageRequired, setStorageRequired 01502 */ 01503 function store( $contentObjectAttribute ) 01504 { 01505 $domTree = $this->domTree(); 01506 if ( $domTree ) 01507 { 01508 if ( is_object( $contentObjectAttribute ) ) 01509 { 01510 $this->storeDOMTree( $domTree, false, $contentObjectAttribute ); 01511 01512 $contentObjectAttribute->setAttribute( 'data_text', $this->ContentObjectAttributeData['data_text'] ); 01513 $contentObjectAttribute->storeData(); 01514 } 01515 else 01516 { 01517 $this->storeDOMTree( $domTree, true, $contentObjectAttribute ); 01518 01519 } 01520 } 01521 01522 $this->setStorageRequired( false ); 01523 } 01524 01525 /*! 01526 \return \c true if the image alias handler is required to store it's contents. 01527 \sa setStorageRequired, store 01528 */ 01529 function isStorageRequired() 01530 { 01531 return isset( $this->ContentObjectAttributeData['DataTypeCustom']['is_storage_required'] ) ? 01532 $this->ContentObjectAttributeData['DataTypeCustom']['is_storage_required'] : 01533 false; 01534 } 01535 01536 /*! 01537 Sets whether storage of the image alias data is required or not. 01538 \sa isStorageRequired, store 01539 */ 01540 function setStorageRequired( $require = true ) 01541 { 01542 $this->ContentObjectAttributeData['DataTypeCustom']['is_storage_required'] = $require; 01543 } 01544 01545 /*! 01546 \return An array structure with information on which attribute 01547 originally created the current data. 01548 01549 This will only contain data if the attribute is a copy of 01550 another attribute, e.g in the case of a new version without an new image upload. 01551 */ 01552 function originalAttributeData() 01553 { 01554 $contentObjectAttributeData = $this->ContentObjectAttributeData; 01555 if ( isset( $contentObjectAttributeData['DataTypeCustom']['original_data'] ) ) 01556 return $contentObjectAttributeData['DataTypeCustom']['original_data']; 01557 01558 $originalData = array( 'attribute_id' => $contentObjectAttributeData['id'], 01559 'attribute_version' => $contentObjectAttributeData['version'], 01560 'attribute_language' => $contentObjectAttributeData['language_code'] ); 01561 $this->setOriginalAttributeData( $originalData ); 01562 return $originalData; 01563 } 01564 01565 /*! 01566 Sets the information on which attribute the data was fetched from. 01567 See eZImageAliasHandler::originalAttributeData() for more information. 01568 */ 01569 function setOriginalAttributeData( $originalData ) 01570 { 01571 $this->ContentObjectAttributeData['DataTypeCustom']['original_data'] = $originalData; 01572 01573 $domTree = $this->domTree(); 01574 $imageOriginalArray = $domTree->getElementsByTagName( "original" ); 01575 if ( $imageOriginalArray->length > 0 ) 01576 { 01577 $imageOriginalNode = $imageOriginalArray->item( 0 ); 01578 $this->createOriginalAttributeXMLData( $imageOriginalNode, $originalData ); 01579 } 01580 } 01581 01582 /*! 01583 Sets the information on which attribute the data was fetched from. 01584 01585 Fetches data from the contentobject attribute \a $contentObjectAttribute and 01586 sets it using setOriginalAttributeData(). 01587 */ 01588 function setOriginalAttributeDataFromAttribute( $contentObjectAttribute ) 01589 { 01590 $originalImageHandler = $contentObjectAttribute->attribute( 'content' ); 01591 $originalAttributeData = $originalImageHandler->originalAttributeData(); 01592 $domTree = $originalImageHandler->domTree(); 01593 $this->setDOMTree( $domTree ); 01594 if ( $originalAttributeData['attribute_id'] ) 01595 { 01596 $this->setOriginalAttributeData( $originalAttributeData ); 01597 } 01598 else 01599 { 01600 $this->setOriginalAttributeDataValues( $contentObjectAttribute->attribute( 'id' ), 01601 $contentObjectAttribute->attribute( 'version' ), 01602 $contentObjectAttribute->attribute( 'language_code' ) ); 01603 } 01604 } 01605 01606 /*! 01607 Sets the information on which attribute the data was fetched from. 01608 01609 Fetches data from the parameters and sets it using setOriginalAttributeData(). 01610 */ 01611 function setOriginalAttributeDataValues( $attributeID, $attributeVersion, $attributeLanguage ) 01612 { 01613 $this->setOriginalAttributeData( array( 'attribute_id' => $attributeID, 01614 'attribute_version' => $attributeVersion, 01615 'attribute_language' => $attributeLanguage ) ); 01616 } 01617 01618 /*! 01619 Set internal serial number 01620 01621 \param val value 01622 */ 01623 function setImageSerialNumber( $val ) 01624 { 01625 $this->ContentObjectAttributeData['DataTypeCustom']['serial_number'] = $val; 01626 } 01627 01628 /*! 01629 \private 01630 \return The internal serial number. 01631 01632 It will check if a serial number exists and return that, if not a new one will be created and returned. 01633 */ 01634 private function imageSerialNumberRaw() 01635 { 01636 return isset( $this->ContentObjectAttributeData['DataTypeCustom']['serial_number'] ) ? 01637 $this->ContentObjectAttributeData['DataTypeCustom']['serial_number'] : 01638 0; 01639 } 01640 01641 /*! 01642 Creates default information. 01643 */ 01644 function generateXMLData() 01645 { 01646 $doc = new DOMDocument( '1.0', 'utf-8' ); 01647 $imageNode = $doc->createElement( "ezimage" ); 01648 $doc->appendChild( $imageNode ); 01649 01650 $fileName = false; 01651 01652 $imageManager = eZImageManager::factory(); 01653 01654 $mimeData = eZMimeType::findByFileContents( $fileName ); 01655 $imageManager->analyzeImage( $mimeData ); 01656 01657 $imageNode->setAttribute( 'serial_number', false ); 01658 $imageNode->setAttribute( 'is_valid', false ); 01659 $imageNode->setAttribute( 'filename', $fileName ); 01660 $imageNode->setAttribute( 'suffix', false ); 01661 $imageNode->setAttribute( 'basename', false ); 01662 $imageNode->setAttribute( 'dirpath', false ); 01663 $imageNode->setAttribute( 'url', false ); 01664 $imageNode->setAttribute( 'original_filename', false ); 01665 $imageNode->setAttribute( 'mime_type', false ); 01666 $imageNode->setAttribute( 'width', false ); 01667 $imageNode->setAttribute( 'height', false ); 01668 $imageNode->setAttribute( 'alternative_text', false ); 01669 $imageNode->setAttribute( 'alias_key', $imageManager->createImageAliasKey( $imageManager->alias( 'original' ) ) ); 01670 $imageNode->setAttribute( 'timestamp', time() ); 01671 01672 $this->createImageInformationNode( $imageNode, $mimeData ); 01673 01674 $this->storeDOMTree( $doc, true, false ); 01675 } 01676 01677 /// \privatesection 01678 /// Contains a some eZContentObjectAttribute's attributes. 01679 public $ContentObjectAttributeData; 01680 /// Deprecated. Contains a reference to the object attribute 01681 public $ContentObjectAttribute; 01682 01683 } 01684 ?>