eZ Publish  [4.0]
ezkeyword.php
Go to the documentation of this file.
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 ?>