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