|
eZ Publish
[trunk]
|
00001 <?php 00002 /** 00003 * File containing the eZKeyword 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 eZKeyword ezkeyword.php 00013 \ingroup eZDatatype 00014 \brief A content datatype which handles keyword index instances 00015 00016 */ 00017 00018 class eZKeyword 00019 { 00020 /*! 00021 Construct a new keyword instance 00022 */ 00023 function eZKeyword( ) 00024 { 00025 } 00026 00027 function attributes() 00028 { 00029 return array( 'keywords', 00030 'keyword_string', 00031 'related_objects', 00032 'related_nodes' ); 00033 } 00034 00035 function hasAttribute( $name ) 00036 { 00037 return in_array( $name, $this->attributes() ); 00038 } 00039 00040 function attribute( $name ) 00041 { 00042 switch ( $name ) 00043 { 00044 case 'keywords' : 00045 { 00046 return $this->KeywordArray; 00047 }break; 00048 00049 case 'keyword_string' : 00050 { 00051 return $this->keywordString(); 00052 }break; 00053 00054 case 'related_objects' : 00055 case 'related_nodes' : 00056 { 00057 return $this->relatedObjects(); 00058 }break; 00059 default: 00060 { 00061 eZDebug::writeError( "Attribute '$name' does not exist", __METHOD__ ); 00062 return null; 00063 }break; 00064 } 00065 } 00066 00067 /*! 00068 Initialze the keyword index 00069 */ 00070 function initializeKeyword( $keywordString ) 00071 { 00072 if ( !is_array( $keywordString ) ) 00073 { 00074 $keywordArray = explode( ',', $keywordString ); 00075 $keywordArray = array_unique ( $keywordArray ); 00076 } 00077 foreach ( array_keys( $keywordArray ) as $key ) 00078 { 00079 if ( trim( $keywordArray[$key] ) != '' ) 00080 { 00081 $this->KeywordArray[$key] = trim( $keywordArray[$key] ); 00082 } 00083 } 00084 } 00085 00086 /*! 00087 Stores the keyword index to database 00088 */ 00089 function store( $attribute ) 00090 { 00091 $db = eZDB::instance(); 00092 00093 $object = $attribute->attribute( 'object' ); 00094 $classID = $object->attribute( 'contentclass_id' ); 00095 00096 // Get already existing keywords 00097 if ( count( $this->KeywordArray ) > 0 ) 00098 { 00099 $escapedKeywordArray = array(); 00100 foreach( $this->KeywordArray as $keyword ) 00101 { 00102 $keyword = $db->escapeString( $keyword ); 00103 $escapedKeywordArray[] = $keyword; 00104 } 00105 $wordsString = implode( '\',\'', $escapedKeywordArray ); 00106 $existingWords = $db->arrayQuery( "SELECT * FROM ezkeyword WHERE keyword IN ( '$wordsString' ) AND class_id='$classID' " ); 00107 } 00108 else 00109 { 00110 $existingWords = array(); 00111 } 00112 00113 $newWordArray = array(); 00114 $existingWordArray = array(); 00115 // Find out which words to store 00116 foreach ( $this->KeywordArray as $keyword ) 00117 { 00118 $wordExists = false; 00119 $wordID = false; 00120 foreach ( $existingWords as $existingKeyword ) 00121 { 00122 if ( $keyword == $existingKeyword['keyword'] ) 00123 { 00124 $wordExists = true; 00125 $wordID = $existingKeyword['id']; 00126 break; 00127 } 00128 } 00129 00130 if ( $wordExists == false ) 00131 { 00132 $newWordArray[] = $keyword; 00133 } 00134 else 00135 { 00136 $existingWordArray[] = array( 'keyword' => $keyword, 'id' => $wordID ); 00137 } 00138 } 00139 00140 // Store every new keyword 00141 $addRelationWordArray = array(); 00142 foreach ( $newWordArray as $keyword ) 00143 { 00144 $keyword = trim( $keyword ); 00145 $keyword = $db->escapeString( $keyword ); 00146 $db->query( "INSERT INTO ezkeyword ( keyword, class_id ) VALUES ( '$keyword', '$classID' )" ); 00147 00148 $keywordID = $db->lastSerialID( 'ezkeyword', 'id' ); 00149 $addRelationWordArray[] = array( 'keyword' => $keywordID, 'id' => $keywordID ); 00150 } 00151 00152 $attributeID = $attribute->attribute( 'id' ); 00153 // Find the words which is new for this attribute 00154 if ( $attributeID !== null ) 00155 { 00156 $currentWordArray = $db->arrayQuery( "SELECT ezkeyword.id, ezkeyword.keyword FROM ezkeyword, ezkeyword_attribute_link 00157 WHERE ezkeyword.id=ezkeyword_attribute_link.keyword_id 00158 AND ezkeyword_attribute_link.objectattribute_id='$attributeID'" ); 00159 } 00160 else 00161 $currentWordArray = array(); 00162 00163 foreach ( $existingWordArray as $existingWord ) 00164 { 00165 $newWord = true; 00166 foreach ( $currentWordArray as $currentWord ) 00167 { 00168 if ( $existingWord['keyword'] == $currentWord['keyword'] ) 00169 { 00170 $newWord = false; 00171 } 00172 } 00173 00174 if ( $newWord == true ) 00175 { 00176 $addRelationWordArray[] = $existingWord; 00177 } 00178 } 00179 00180 // Find the current words no longer used 00181 $removeWordRelationIDArray = array(); 00182 foreach ( $currentWordArray as $currentWord ) 00183 { 00184 $stillUsed = false; 00185 foreach ( $this->KeywordArray as $keyword ) 00186 { 00187 if ( $keyword == $currentWord['keyword'] ) 00188 $stillUsed = true; 00189 } 00190 if ( !$stillUsed ) 00191 { 00192 $removeWordRelationIDArray[] = $currentWord['id']; 00193 } 00194 } 00195 00196 if ( count( $removeWordRelationIDArray ) > 0 ) 00197 { 00198 $removeIDString = implode( ', ', $removeWordRelationIDArray ); 00199 $db->query( "DELETE FROM ezkeyword_attribute_link WHERE keyword_id IN ( $removeIDString ) AND ezkeyword_attribute_link.objectattribute_id='$attributeID'" ); 00200 } 00201 00202 // Only store relation to new keywords 00203 // Store relations to keyword for this content object 00204 foreach ( $addRelationWordArray as $keywordArray ) 00205 { 00206 $db->query( "INSERT INTO ezkeyword_attribute_link ( keyword_id, objectattribute_id ) VALUES ( '" . $keywordArray['id'] ."', '" . $attribute->attribute( 'id' ) . "' )" ); 00207 } 00208 00209 /* Clean up no longer used words: 00210 * 1. Select words having no links. 00211 * 2. Delete them. 00212 * We cannot do this in one cross-table DELETE since older MySQL versions do not support this. 00213 */ 00214 if ( $db->databaseName() == 'oracle' ) 00215 { 00216 $query = 00217 'SELECT ezkeyword.id FROM ezkeyword, ezkeyword_attribute_link ' . 00218 'WHERE ezkeyword.id=ezkeyword_attribute_link.keyword_id(+) AND ' . 00219 'ezkeyword_attribute_link.keyword_id IS NULL'; 00220 } 00221 else 00222 { 00223 $query = 00224 'SELECT ezkeyword.id FROM ezkeyword LEFT JOIN ezkeyword_attribute_link ' . 00225 ' ON ezkeyword.id=ezkeyword_attribute_link.keyword_id' . 00226 ' WHERE ezkeyword_attribute_link.keyword_id IS NULL'; 00227 } 00228 $unusedWordsIDs = $db->arrayQuery( $query ); 00229 foreach ( $unusedWordsIDs as $wordID ) 00230 $db->query( 'DELETE FROM ezkeyword WHERE id=' . $wordID['id'] ); 00231 } 00232 00233 /*! 00234 Fetches the keywords for the given attribute. 00235 */ 00236 function fetch( &$attribute ) 00237 { 00238 if ( $attribute->attribute( 'id' ) === null ) 00239 return; 00240 00241 $db = eZDB::instance(); 00242 $wordArray = $db->arrayQuery( "SELECT ezkeyword.keyword FROM ezkeyword_attribute_link, ezkeyword 00243 WHERE ezkeyword_attribute_link.keyword_id=ezkeyword.id AND 00244 ezkeyword_attribute_link.objectattribute_id='" . $attribute->attribute( 'id' ) ."' " ); 00245 00246 $this->ObjectAttributeID = $attribute->attribute( 'id' ); 00247 foreach ( array_keys( $wordArray ) as $wordKey ) 00248 { 00249 $this->KeywordArray[] = $wordArray[$wordKey]['keyword']; 00250 } 00251 $this->KeywordArray = array_unique ( $this->KeywordArray ); 00252 } 00253 00254 /*! 00255 Sets the keyword index 00256 */ 00257 function setKeywordArray( $keywords ) 00258 { 00259 $this->KeywordArray = $keywords; 00260 } 00261 00262 /*! 00263 Returns the keyword index 00264 */ 00265 function keywordArray( ) 00266 { 00267 return $this->KeywordArray; 00268 } 00269 00270 /*! 00271 Returns the keywords as a string 00272 */ 00273 function keywordString() 00274 { 00275 return implode( ', ', $this->KeywordArray ); 00276 } 00277 00278 /*! 00279 Returns the objects which have at least one keyword in common 00280 00281 \return an array of eZContentObjectTreeNode instances, or null if the attribute is not stored yet 00282 */ 00283 function relatedObjects() 00284 { 00285 $return = false; 00286 if ( $this->ObjectAttributeID ) 00287 { 00288 $return = array(); 00289 00290 // Fetch words 00291 $db = eZDB::instance(); 00292 00293 $wordArray = $db->arrayQuery( "SELECT * FROM ezkeyword_attribute_link 00294 WHERE objectattribute_id='" . $this->ObjectAttributeID ."' " ); 00295 00296 $keywordIDArray = array(); 00297 // Fetch the objects which have one of these words 00298 foreach ( $wordArray as $word ) 00299 { 00300 $keywordIDArray[] = $word['keyword_id']; 00301 } 00302 00303 $keywordCondition = $db->generateSQLINStatement( $keywordIDArray, 'keyword_id' ); 00304 00305 if ( count( $keywordIDArray ) > 0 ) 00306 { 00307 $objectArray = $db->arrayQuery( "SELECT DISTINCT ezcontentobject_attribute.contentobject_id FROM ezkeyword_attribute_link, ezcontentobject_attribute 00308 WHERE $keywordCondition AND 00309 ezcontentobject_attribute.id = ezkeyword_attribute_link.objectattribute_id 00310 AND objectattribute_id <> '" . $this->ObjectAttributeID ."' " ); 00311 00312 $objectIDArray = array(); 00313 foreach ( $objectArray as $object ) 00314 { 00315 $objectIDArray[] = $object['contentobject_id']; 00316 } 00317 00318 if ( count( $objectIDArray ) > 0 ) 00319 { 00320 $aNodes = eZContentObjectTreeNode::findMainNodeArray( $objectIDArray ); 00321 00322 foreach ( $aNodes as $key => $node ) 00323 { 00324 $theObject = $node->object(); 00325 if ( $theObject->canRead() ) 00326 { 00327 $return[] = $node; 00328 } 00329 } 00330 } 00331 } 00332 } 00333 return $return; 00334 } 00335 00336 /// Contains the keywords 00337 public $KeywordArray = array(); 00338 00339 /// Contains the ID attribute if fetched 00340 public $ObjectAttributeID = false; 00341 } 00342 00343 ?>