/kernel/classes/datatypes/ezkeyword/ezkeyword.php

https://bitbucket.org/ericsagnes/ezpublish-multisite · PHP · 343 lines · 247 code · 40 blank · 56 comment · 25 complexity · b5e0ada8a0a2e1827eff97281d3aca28 MD5 · raw file

  1. <?php
  2. /**
  3. * File containing the eZKeyword class.
  4. *
  5. * @copyright Copyright (C) 1999-2012 eZ Systems AS. All rights reserved.
  6. * @license http://www.gnu.org/licenses/gpl-2.0.txt GNU General Public License v2
  7. * @version 2012.8
  8. * @package kernel
  9. */
  10. /*!
  11. \class eZKeyword ezkeyword.php
  12. \ingroup eZDatatype
  13. \brief A content datatype which handles keyword index instances
  14. */
  15. class eZKeyword
  16. {
  17. /*!
  18. Construct a new keyword instance
  19. */
  20. function eZKeyword( )
  21. {
  22. }
  23. function attributes()
  24. {
  25. return array( 'keywords',
  26. 'keyword_string',
  27. 'related_objects',
  28. 'related_nodes' );
  29. }
  30. function hasAttribute( $name )
  31. {
  32. return in_array( $name, $this->attributes() );
  33. }
  34. function attribute( $name )
  35. {
  36. switch ( $name )
  37. {
  38. case 'keywords' :
  39. {
  40. return $this->KeywordArray;
  41. }break;
  42. case 'keyword_string' :
  43. {
  44. return $this->keywordString();
  45. }break;
  46. case 'related_objects' :
  47. case 'related_nodes' :
  48. {
  49. return $this->relatedObjects();
  50. }break;
  51. default:
  52. {
  53. eZDebug::writeError( "Attribute '$name' does not exist", __METHOD__ );
  54. return null;
  55. }break;
  56. }
  57. }
  58. /*!
  59. Initialze the keyword index
  60. */
  61. function initializeKeyword( $keywordString )
  62. {
  63. if ( !is_array( $keywordString ) )
  64. {
  65. $keywordArray = explode( ',', $keywordString );
  66. $keywordArray = array_unique ( $keywordArray );
  67. }
  68. foreach ( array_keys( $keywordArray ) as $key )
  69. {
  70. if ( trim( $keywordArray[$key] ) != '' )
  71. {
  72. $this->KeywordArray[$key] = trim( $keywordArray[$key] );
  73. }
  74. }
  75. }
  76. /*!
  77. Stores the keyword index to database
  78. */
  79. function store( $attribute )
  80. {
  81. $db = eZDB::instance();
  82. $object = $attribute->attribute( 'object' );
  83. $classID = $object->attribute( 'contentclass_id' );
  84. // Get already existing keywords
  85. if ( count( $this->KeywordArray ) > 0 )
  86. {
  87. $escapedKeywordArray = array();
  88. foreach( $this->KeywordArray as $keyword )
  89. {
  90. $keyword = $db->escapeString( $keyword );
  91. $escapedKeywordArray[] = $keyword;
  92. }
  93. $wordsString = implode( '\',\'', $escapedKeywordArray );
  94. $existingWords = $db->arrayQuery( "SELECT * FROM ezkeyword WHERE keyword IN ( '$wordsString' ) AND class_id='$classID' " );
  95. }
  96. else
  97. {
  98. $existingWords = array();
  99. }
  100. $newWordArray = array();
  101. $existingWordArray = array();
  102. // Find out which words to store
  103. foreach ( $this->KeywordArray as $keyword )
  104. {
  105. $wordExists = false;
  106. $wordID = false;
  107. foreach ( $existingWords as $existingKeyword )
  108. {
  109. if ( $keyword == $existingKeyword['keyword'] )
  110. {
  111. $wordExists = true;
  112. $wordID = $existingKeyword['id'];
  113. break;
  114. }
  115. }
  116. if ( $wordExists == false )
  117. {
  118. $newWordArray[] = $keyword;
  119. }
  120. else
  121. {
  122. $existingWordArray[] = array( 'keyword' => $keyword, 'id' => $wordID );
  123. }
  124. }
  125. // Store every new keyword
  126. $addRelationWordArray = array();
  127. foreach ( $newWordArray as $keyword )
  128. {
  129. $keyword = trim( $keyword );
  130. $keyword = $db->escapeString( $keyword );
  131. $db->query( "INSERT INTO ezkeyword ( keyword, class_id ) VALUES ( '$keyword', '$classID' )" );
  132. $keywordID = $db->lastSerialID( 'ezkeyword', 'id' );
  133. $addRelationWordArray[] = array( 'keyword' => $keywordID, 'id' => $keywordID );
  134. }
  135. $attributeID = $attribute->attribute( 'id' );
  136. // Find the words which is new for this attribute
  137. if ( $attributeID !== null )
  138. {
  139. $currentWordArray = $db->arrayQuery( "SELECT ezkeyword.id, ezkeyword.keyword FROM ezkeyword, ezkeyword_attribute_link
  140. WHERE ezkeyword.id=ezkeyword_attribute_link.keyword_id
  141. AND ezkeyword_attribute_link.objectattribute_id='$attributeID'" );
  142. }
  143. else
  144. $currentWordArray = array();
  145. foreach ( $existingWordArray as $existingWord )
  146. {
  147. $newWord = true;
  148. foreach ( $currentWordArray as $currentWord )
  149. {
  150. if ( $existingWord['keyword'] == $currentWord['keyword'] )
  151. {
  152. $newWord = false;
  153. }
  154. }
  155. if ( $newWord == true )
  156. {
  157. $addRelationWordArray[] = $existingWord;
  158. }
  159. }
  160. // Find the current words no longer used
  161. $removeWordRelationIDArray = array();
  162. foreach ( $currentWordArray as $currentWord )
  163. {
  164. $stillUsed = false;
  165. foreach ( $this->KeywordArray as $keyword )
  166. {
  167. if ( $keyword == $currentWord['keyword'] )
  168. $stillUsed = true;
  169. }
  170. if ( !$stillUsed )
  171. {
  172. $removeWordRelationIDArray[] = $currentWord['id'];
  173. }
  174. }
  175. if ( count( $removeWordRelationIDArray ) > 0 )
  176. {
  177. $removeIDString = implode( ', ', $removeWordRelationIDArray );
  178. $db->query( "DELETE FROM ezkeyword_attribute_link WHERE keyword_id IN ( $removeIDString ) AND ezkeyword_attribute_link.objectattribute_id='$attributeID'" );
  179. }
  180. // Only store relation to new keywords
  181. // Store relations to keyword for this content object
  182. foreach ( $addRelationWordArray as $keywordArray )
  183. {
  184. $db->query( "INSERT INTO ezkeyword_attribute_link ( keyword_id, objectattribute_id ) VALUES ( '" . $keywordArray['id'] ."', '" . $attribute->attribute( 'id' ) . "' )" );
  185. }
  186. /* Clean up no longer used words:
  187. * 1. Select words having no links.
  188. * 2. Delete them.
  189. * We cannot do this in one cross-table DELETE since older MySQL versions do not support this.
  190. */
  191. if ( $db->databaseName() == 'oracle' )
  192. {
  193. $query =
  194. 'SELECT ezkeyword.id FROM ezkeyword, ezkeyword_attribute_link ' .
  195. 'WHERE ezkeyword.id=ezkeyword_attribute_link.keyword_id(+) AND ' .
  196. 'ezkeyword_attribute_link.keyword_id IS NULL';
  197. }
  198. else
  199. {
  200. $query =
  201. 'SELECT ezkeyword.id FROM ezkeyword LEFT JOIN ezkeyword_attribute_link ' .
  202. ' ON ezkeyword.id=ezkeyword_attribute_link.keyword_id' .
  203. ' WHERE ezkeyword_attribute_link.keyword_id IS NULL';
  204. }
  205. $unusedWordsIDs = $db->arrayQuery( $query );
  206. foreach ( $unusedWordsIDs as $wordID )
  207. $db->query( 'DELETE FROM ezkeyword WHERE id=' . $wordID['id'] );
  208. }
  209. /*!
  210. Fetches the keywords for the given attribute.
  211. */
  212. function fetch( &$attribute )
  213. {
  214. if ( $attribute->attribute( 'id' ) === null )
  215. return;
  216. $db = eZDB::instance();
  217. $wordArray = $db->arrayQuery( "SELECT ezkeyword.keyword FROM ezkeyword_attribute_link, ezkeyword
  218. WHERE ezkeyword_attribute_link.keyword_id=ezkeyword.id AND
  219. ezkeyword_attribute_link.objectattribute_id='" . $attribute->attribute( 'id' ) ."' " );
  220. $this->ObjectAttributeID = $attribute->attribute( 'id' );
  221. foreach ( array_keys( $wordArray ) as $wordKey )
  222. {
  223. $this->KeywordArray[] = $wordArray[$wordKey]['keyword'];
  224. }
  225. $this->KeywordArray = array_unique ( $this->KeywordArray );
  226. }
  227. /*!
  228. Sets the keyword index
  229. */
  230. function setKeywordArray( $keywords )
  231. {
  232. $this->KeywordArray = $keywords;
  233. }
  234. /*!
  235. Returns the keyword index
  236. */
  237. function keywordArray( )
  238. {
  239. return $this->KeywordArray;
  240. }
  241. /*!
  242. Returns the keywords as a string
  243. */
  244. function keywordString()
  245. {
  246. return implode( ', ', $this->KeywordArray );
  247. }
  248. /*!
  249. Returns the objects which have at least one keyword in common
  250. \return an array of eZContentObjectTreeNode instances, or null if the attribute is not stored yet
  251. */
  252. function relatedObjects()
  253. {
  254. $return = false;
  255. if ( $this->ObjectAttributeID )
  256. {
  257. $return = array();
  258. // Fetch words
  259. $db = eZDB::instance();
  260. $wordArray = $db->arrayQuery( "SELECT * FROM ezkeyword_attribute_link
  261. WHERE objectattribute_id='" . $this->ObjectAttributeID ."' " );
  262. $keywordIDArray = array();
  263. // Fetch the objects which have one of these words
  264. foreach ( $wordArray as $word )
  265. {
  266. $keywordIDArray[] = $word['keyword_id'];
  267. }
  268. $keywordCondition = $db->generateSQLINStatement( $keywordIDArray, 'keyword_id' );
  269. if ( count( $keywordIDArray ) > 0 )
  270. {
  271. $objectArray = $db->arrayQuery( "SELECT DISTINCT ezcontentobject_attribute.contentobject_id FROM ezkeyword_attribute_link, ezcontentobject_attribute
  272. WHERE $keywordCondition AND
  273. ezcontentobject_attribute.id = ezkeyword_attribute_link.objectattribute_id
  274. AND objectattribute_id <> '" . $this->ObjectAttributeID ."' " );
  275. $objectIDArray = array();
  276. foreach ( $objectArray as $object )
  277. {
  278. $objectIDArray[] = $object['contentobject_id'];
  279. }
  280. if ( count( $objectIDArray ) > 0 )
  281. {
  282. $aNodes = eZContentObjectTreeNode::findMainNodeArray( $objectIDArray );
  283. foreach ( $aNodes as $key => $node )
  284. {
  285. $theObject = $node->object();
  286. if ( $theObject->canRead() )
  287. {
  288. $return[] = $node;
  289. }
  290. }
  291. }
  292. }
  293. }
  294. return $return;
  295. }
  296. /// Contains the keywords
  297. public $KeywordArray = array();
  298. /// Contains the ID attribute if fetched
  299. public $ObjectAttributeID = false;
  300. }
  301. ?>