PageRenderTime 38ms CodeModel.GetById 11ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://github.com/granitegreg/ezpublish
PHP | 363 lines | 247 code | 40 blank | 76 comment | 25 complexity | 84f0d9bab650f44b2fb03f5529aa4b10 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. //
  3. // Definition of eZKeyword class
  4. //
  5. // Created on: <29-Apr-2003 15:18:15 bf>
  6. //
  7. // ## BEGIN COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
  8. // SOFTWARE NAME: eZ Publish
  9. // SOFTWARE RELEASE: 4.1.x
  10. // COPYRIGHT NOTICE: Copyright (C) 1999-2011 eZ Systems AS
  11. // SOFTWARE LICENSE: GNU General Public License v2.0
  12. // NOTICE: >
  13. // This program is free software; you can redistribute it and/or
  14. // modify it under the terms of version 2.0 of the GNU General
  15. // Public License as published by the Free Software Foundation.
  16. //
  17. // This program is distributed in the hope that it will be useful,
  18. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. // GNU General Public License for more details.
  21. //
  22. // You should have received a copy of version 2.0 of the GNU General
  23. // Public License along with this program; if not, write to the Free
  24. // Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
  25. // MA 02110-1301, USA.
  26. //
  27. //
  28. // ## END COPYRIGHT, LICENSE AND WARRANTY NOTICE ##
  29. //
  30. /*!
  31. \class eZKeyword ezkeyword.php
  32. \ingroup eZDatatype
  33. \brief A content datatype which handles keyword index instances
  34. */
  35. class eZKeyword
  36. {
  37. /*!
  38. Construct a new keyword instance
  39. */
  40. function eZKeyword( )
  41. {
  42. }
  43. function attributes()
  44. {
  45. return array( 'keywords',
  46. 'keyword_string',
  47. 'related_objects',
  48. 'related_nodes' );
  49. }
  50. function hasAttribute( $name )
  51. {
  52. return in_array( $name, $this->attributes() );
  53. }
  54. function attribute( $name )
  55. {
  56. switch ( $name )
  57. {
  58. case 'keywords' :
  59. {
  60. return $this->KeywordArray;
  61. }break;
  62. case 'keyword_string' :
  63. {
  64. return $this->keywordString();
  65. }break;
  66. case 'related_objects' :
  67. case 'related_nodes' :
  68. {
  69. return $this->relatedObjects();
  70. }break;
  71. default:
  72. {
  73. eZDebug::writeError( "Attribute '$name' does not exist", __METHOD__ );
  74. return null;
  75. }break;
  76. }
  77. }
  78. /*!
  79. Initialze the keyword index
  80. */
  81. function initializeKeyword( $keywordString )
  82. {
  83. if ( !is_array( $keywordString ) )
  84. {
  85. $keywordArray = explode( ',', $keywordString );
  86. $keywordArray = array_unique ( $keywordArray );
  87. }
  88. foreach ( array_keys( $keywordArray ) as $key )
  89. {
  90. if ( trim( $keywordArray[$key] ) != '' )
  91. {
  92. $this->KeywordArray[$key] = trim( $keywordArray[$key] );
  93. }
  94. }
  95. }
  96. /*!
  97. Stores the keyword index to database
  98. */
  99. function store( $attribute )
  100. {
  101. $db = eZDB::instance();
  102. $object = $attribute->attribute( 'object' );
  103. $classID = $object->attribute( 'contentclass_id' );
  104. // Get already existing keywords
  105. if ( count( $this->KeywordArray ) > 0 )
  106. {
  107. $escapedKeywordArray = array();
  108. foreach( $this->KeywordArray as $keyword )
  109. {
  110. $keyword = $db->escapeString( $keyword );
  111. $escapedKeywordArray[] = $keyword;
  112. }
  113. $wordsString = implode( '\',\'', $escapedKeywordArray );
  114. $existingWords = $db->arrayQuery( "SELECT * FROM ezkeyword WHERE keyword IN ( '$wordsString' ) AND class_id='$classID' " );
  115. }
  116. else
  117. {
  118. $existingWords = array();
  119. }
  120. $newWordArray = array();
  121. $existingWordArray = array();
  122. // Find out which words to store
  123. foreach ( $this->KeywordArray as $keyword )
  124. {
  125. $wordExists = false;
  126. $wordID = false;
  127. foreach ( $existingWords as $existingKeyword )
  128. {
  129. if ( $keyword == $existingKeyword['keyword'] )
  130. {
  131. $wordExists = true;
  132. $wordID = $existingKeyword['id'];
  133. break;
  134. }
  135. }
  136. if ( $wordExists == false )
  137. {
  138. $newWordArray[] = $keyword;
  139. }
  140. else
  141. {
  142. $existingWordArray[] = array( 'keyword' => $keyword, 'id' => $wordID );
  143. }
  144. }
  145. // Store every new keyword
  146. $addRelationWordArray = array();
  147. foreach ( $newWordArray as $keyword )
  148. {
  149. $keyword = trim( $keyword );
  150. $keyword = $db->escapeString( $keyword );
  151. $db->query( "INSERT INTO ezkeyword ( keyword, class_id ) VALUES ( '$keyword', '$classID' )" );
  152. $keywordID = $db->lastSerialID( 'ezkeyword', 'id' );
  153. $addRelationWordArray[] = array( 'keyword' => $keywordID, 'id' => $keywordID );
  154. }
  155. $attributeID = $attribute->attribute( 'id' );
  156. // Find the words which is new for this attribute
  157. if ( $attributeID !== null )
  158. {
  159. $currentWordArray = $db->arrayQuery( "SELECT ezkeyword.id, ezkeyword.keyword FROM ezkeyword, ezkeyword_attribute_link
  160. WHERE ezkeyword.id=ezkeyword_attribute_link.keyword_id
  161. AND ezkeyword_attribute_link.objectattribute_id='$attributeID'" );
  162. }
  163. else
  164. $currentWordArray = array();
  165. foreach ( $existingWordArray as $existingWord )
  166. {
  167. $newWord = true;
  168. foreach ( $currentWordArray as $currentWord )
  169. {
  170. if ( $existingWord['keyword'] == $currentWord['keyword'] )
  171. {
  172. $newWord = false;
  173. }
  174. }
  175. if ( $newWord == true )
  176. {
  177. $addRelationWordArray[] = $existingWord;
  178. }
  179. }
  180. // Find the current words no longer used
  181. $removeWordRelationIDArray = array();
  182. foreach ( $currentWordArray as $currentWord )
  183. {
  184. $stillUsed = false;
  185. foreach ( $this->KeywordArray as $keyword )
  186. {
  187. if ( $keyword == $currentWord['keyword'] )
  188. $stillUsed = true;
  189. }
  190. if ( !$stillUsed )
  191. {
  192. $removeWordRelationIDArray[] = $currentWord['id'];
  193. }
  194. }
  195. if ( count( $removeWordRelationIDArray ) > 0 )
  196. {
  197. $removeIDString = implode( ', ', $removeWordRelationIDArray );
  198. $db->query( "DELETE FROM ezkeyword_attribute_link WHERE keyword_id IN ( $removeIDString ) AND ezkeyword_attribute_link.objectattribute_id='$attributeID'" );
  199. }
  200. // Only store relation to new keywords
  201. // Store relations to keyword for this content object
  202. foreach ( $addRelationWordArray as $keywordArray )
  203. {
  204. $db->query( "INSERT INTO ezkeyword_attribute_link ( keyword_id, objectattribute_id ) VALUES ( '" . $keywordArray['id'] ."', '" . $attribute->attribute( 'id' ) . "' )" );
  205. }
  206. /* Clean up no longer used words:
  207. * 1. Select words having no links.
  208. * 2. Delete them.
  209. * We cannot do this in one cross-table DELETE since older MySQL versions do not support this.
  210. */
  211. if ( $db->databaseName() == 'oracle' )
  212. {
  213. $query =
  214. 'SELECT ezkeyword.id FROM ezkeyword, ezkeyword_attribute_link ' .
  215. 'WHERE ezkeyword.id=ezkeyword_attribute_link.keyword_id(+) AND ' .
  216. 'ezkeyword_attribute_link.keyword_id IS NULL';
  217. }
  218. else
  219. {
  220. $query =
  221. 'SELECT ezkeyword.id FROM ezkeyword LEFT JOIN ezkeyword_attribute_link ' .
  222. ' ON ezkeyword.id=ezkeyword_attribute_link.keyword_id' .
  223. ' WHERE ezkeyword_attribute_link.keyword_id IS NULL';
  224. }
  225. $unusedWordsIDs = $db->arrayQuery( $query );
  226. foreach ( $unusedWordsIDs as $wordID )
  227. $db->query( 'DELETE FROM ezkeyword WHERE id=' . $wordID['id'] );
  228. }
  229. /*!
  230. Fetches the keywords for the given attribute.
  231. */
  232. function fetch( &$attribute )
  233. {
  234. if ( $attribute->attribute( 'id' ) === null )
  235. return;
  236. $db = eZDB::instance();
  237. $wordArray = $db->arrayQuery( "SELECT ezkeyword.keyword FROM ezkeyword_attribute_link, ezkeyword
  238. WHERE ezkeyword_attribute_link.keyword_id=ezkeyword.id AND
  239. ezkeyword_attribute_link.objectattribute_id='" . $attribute->attribute( 'id' ) ."' " );
  240. $this->ObjectAttributeID = $attribute->attribute( 'id' );
  241. foreach ( array_keys( $wordArray ) as $wordKey )
  242. {
  243. $this->KeywordArray[] = $wordArray[$wordKey]['keyword'];
  244. }
  245. $this->KeywordArray = array_unique ( $this->KeywordArray );
  246. }
  247. /*!
  248. Sets the keyword index
  249. */
  250. function setKeywordArray( $keywords )
  251. {
  252. $this->KeywordArray = $keywords;
  253. }
  254. /*!
  255. Returns the keyword index
  256. */
  257. function keywordArray( )
  258. {
  259. return $this->KeywordArray;
  260. }
  261. /*!
  262. Returns the keywords as a string
  263. */
  264. function keywordString()
  265. {
  266. return implode( ', ', $this->KeywordArray );
  267. }
  268. /*!
  269. Returns the objects which have at least one keyword in common
  270. \return an array of eZContentObjectTreeNode instances, or null if the attribute is not stored yet
  271. */
  272. function relatedObjects()
  273. {
  274. $return = false;
  275. if ( $this->ObjectAttributeID )
  276. {
  277. $return = array();
  278. // Fetch words
  279. $db = eZDB::instance();
  280. $wordArray = $db->arrayQuery( "SELECT * FROM ezkeyword_attribute_link
  281. WHERE objectattribute_id='" . $this->ObjectAttributeID ."' " );
  282. $keywordIDArray = array();
  283. // Fetch the objects which have one of these words
  284. foreach ( $wordArray as $word )
  285. {
  286. $keywordIDArray[] = $word['keyword_id'];
  287. }
  288. $keywordCondition = $db->generateSQLINStatement( $keywordIDArray, 'keyword_id' );
  289. if ( count( $keywordIDArray ) > 0 )
  290. {
  291. $objectArray = $db->arrayQuery( "SELECT DISTINCT ezcontentobject_attribute.contentobject_id FROM ezkeyword_attribute_link, ezcontentobject_attribute
  292. WHERE $keywordCondition AND
  293. ezcontentobject_attribute.id = ezkeyword_attribute_link.objectattribute_id
  294. AND objectattribute_id <> '" . $this->ObjectAttributeID ."' " );
  295. $objectIDArray = array();
  296. foreach ( $objectArray as $object )
  297. {
  298. $objectIDArray[] = $object['contentobject_id'];
  299. }
  300. if ( count( $objectIDArray ) > 0 )
  301. {
  302. $aNodes = eZContentObjectTreeNode::findMainNodeArray( $objectIDArray );
  303. foreach ( $aNodes as $key => $node )
  304. {
  305. $theObject = $node->object();
  306. if ( $theObject->canRead() )
  307. {
  308. $return[] = $node;
  309. }
  310. }
  311. }
  312. }
  313. }
  314. return $return;
  315. }
  316. /// Contains the keywords
  317. public $KeywordArray = array();
  318. /// Contains the ID attribute if fetched
  319. public $ObjectAttributeID = false;
  320. }
  321. ?>