/kernel/classes/ezurlaliasquery.php

https://github.com/zerustech/ezpublish · PHP · 334 lines · 209 code · 23 blank · 102 comment · 41 complexity · edc49f0bcaa945b0c746a77242d147fd MD5 · raw file

  1. <?php
  2. /**
  3. * File containing the eZURLAliasFilter class.
  4. *
  5. * @copyright Copyright (C) eZ Systems AS. All rights reserved.
  6. * @license For full copyright and license information view LICENSE file distributed with this source code.
  7. * @version //autogentag//
  8. * @package kernel
  9. */
  10. /*!
  11. \class eZURLAliasQuery ezurlaliasquery.php
  12. \brief Handles querying of URL aliases with different filters
  13. To use this class instantiate it and then fill in the public
  14. properties with the wanted values. When finished call count()
  15. and/or fetchAll() to perform the wanted operation. Repeated
  16. calls will simply return the cached values.
  17. If you change the properties afterwards call prepare() to reset
  18. internally cached values.
  19. Objects of this class can also be sent to the template system
  20. as a variable and the properties can be accessed directly
  21. including 'count' for the count() function and 'items' for the
  22. 'fetchAll' function.
  23. */
  24. /*!
  25. \todo The hasAttribute, attribute and setAttribute functions can be turned into properties for PHP 5.
  26. */
  27. class eZURLAliasQuery
  28. {
  29. /*!
  30. Array of action values to include, set to null to fetch all kinds.
  31. e.g. eznode:60
  32. */
  33. public $actions;
  34. /*!
  35. Array of action types to include, set to null to fetch all kinds.
  36. e.g. eznode
  37. */
  38. public $actionTypes;
  39. /*!
  40. Array of action types to exclude, set to null to disable.
  41. e.g. eznode
  42. */
  43. public $actionTypesEx;
  44. /*!
  45. If non-null it forces only elements with this parent to be considered.
  46. */
  47. public $paren;
  48. /*!
  49. If non-null it forces only elements with this text to be considered.
  50. */
  51. public $text;
  52. /*!
  53. Type of elements to count, use 'name' for only real names for actions, 'alias' for only aliases to the actions or 'all' for real and aliases.
  54. */
  55. public $type = 'alias';
  56. /*!
  57. If true languages are filtered, otherwise all languages are fetched.
  58. */
  59. public $languages = true;
  60. /*!
  61. The offset to start the fetch.
  62. \note It only applies to fetchAll()
  63. */
  64. public $offset = 0;
  65. /*!
  66. The max limit of the fetch.
  67. \note It only applies to fetchAll()
  68. */
  69. public $limit = 15;
  70. /*!
  71. The order in which elements are fetched, refers the the DB column of the table.
  72. \note It only applies to fetchAll()
  73. */
  74. public $order = 'text';
  75. /*!
  76. \private
  77. Cached value of partial query, used for both count() and fetchAll().
  78. */
  79. public $query;
  80. /*!
  81. \private
  82. Cached value of the total count.
  83. */
  84. public $count;
  85. /*!
  86. \private
  87. Cached value of the fetch items.
  88. */
  89. public $items;
  90. function hasAttribute( $name )
  91. {
  92. return $name !== "query" && array_key_exists( $name, get_object_vars( $this ) );
  93. }
  94. function attribute( $name )
  95. {
  96. switch ( $name )
  97. {
  98. case 'count':
  99. {
  100. return $this->count();
  101. } break;
  102. case 'items':
  103. {
  104. return $this->fetchAll();
  105. } break;
  106. default:
  107. {
  108. return $this->$name;
  109. } break;
  110. }
  111. }
  112. function setAttribute( $name, $value )
  113. {
  114. $this->$name = $value;
  115. $this->query = null;
  116. $this->count = null;
  117. $this->items = null;
  118. }
  119. /*!
  120. Resets all internally cached values. This must be called
  121. if the properties have been changed after count() or
  122. fetchAll() has been used.
  123. */
  124. function prepare()
  125. {
  126. $this->query = null;
  127. $this->count = null;
  128. $this->items = null;
  129. }
  130. /*!
  131. Counts the total number of items available using the current
  132. filters as specified with the properties.
  133. \note Can also be fetched from templates by using the 'count' property.
  134. */
  135. function count()
  136. {
  137. if ( $this->count !== null )
  138. return $this->count;
  139. if ( $this->query === null )
  140. {
  141. $this->query = $this->generateSQL();
  142. }
  143. if ( $this->query === false )
  144. return 0;
  145. $query = "SELECT count(*) AS count {$this->query}";
  146. $db = eZDB::instance();
  147. $rows = $db->arrayQuery( $query );
  148. if ( count( $rows ) == 0 )
  149. $this->count = 0;
  150. else
  151. $this->count = $rows[0]['count'];
  152. return $this->count;
  153. }
  154. /*!
  155. Fetches the items in the current range (offset/limit) using the current
  156. filters as specified with the properties.
  157. \note Can also be fetched from templates by using the 'items' property.
  158. */
  159. function fetchAll()
  160. {
  161. if ( $this->items !== null )
  162. return $this->items;
  163. if ( $this->query === null )
  164. {
  165. $this->query = $this->generateSQL();
  166. }
  167. if ( $this->query === false )
  168. return array();
  169. $query = "SELECT * {$this->query} ORDER BY {$this->order}";
  170. $params = array( 'offset' => $this->offset,
  171. 'limit' => $this->limit );
  172. $db = eZDB::instance();
  173. $rows = $db->arrayQuery( $query, $params );
  174. if ( count( $rows ) == 0 )
  175. $this->items = array();
  176. else
  177. $this->items = eZURLAliasQuery::makeList( $rows );
  178. return $this->items;
  179. }
  180. /*!
  181. \private
  182. Generates the common part of the SQL using the properties as filters and returns it.
  183. */
  184. protected function generateSQL()
  185. {
  186. if ( !in_array( $this->type, array( 'name', 'alias', 'all' ) ) )
  187. {
  188. eZDebug::writeError( "Parameter \$type must be one of name, alias or all. The value which was used was '{$this->type}'." );
  189. return null;
  190. }
  191. $db = eZDB::instance();
  192. if ( $this->languages === true )
  193. {
  194. $langMask = trim( eZContentLanguage::languagesSQLFilter( 'ezurlalias_ml', 'lang_mask' ) );
  195. $conds[] = "($langMask)";
  196. }
  197. if ( $this->paren !== null )
  198. {
  199. $conds[] = "parent = {$this->paren}";
  200. }
  201. if ( $this->text !== null )
  202. {
  203. $conds[] = "text_md5 = " . $db->md5( "'" . $db->escapeString( $this->text ) . "'" );
  204. }
  205. if ( $this->actions !== null )
  206. {
  207. // Check for conditions which will return no rows.
  208. if ( count( $this->actions ) == 0 )
  209. return false;
  210. if ( count( $this->actions ) == 1 )
  211. {
  212. $action = $this->actions[0];
  213. $actionStr = $db->escapeString( $action );
  214. $conds[] = "action = '$actionStr'";
  215. }
  216. else
  217. {
  218. $actions = array();
  219. foreach ( $this->actions as $action )
  220. {
  221. $actions[] = "'" . $db->escapeString( $action ) . "'";
  222. }
  223. $conds[] = "action IN (" . join( ", ", $actions ) . ")";
  224. }
  225. }
  226. $actionTypes = null;
  227. if ( $this->actionTypes !== null )
  228. {
  229. $actionTypes = $this->actionTypes;
  230. }
  231. if ( $this->actionTypesEx !== null )
  232. {
  233. if ( $actionTypes == null )
  234. {
  235. $rows = $db->arrayQuery( "SELECT DISTINCT action_type FROM ezurlalias_ml" );
  236. $actionTypes = array();
  237. foreach ( $rows as $row )
  238. {
  239. $actionTypes[] = $row['action_type'];
  240. }
  241. }
  242. $actionTypes = array_values( array_diff( $actionTypes, $this->actionTypesEx ) );
  243. }
  244. if ( $actionTypes !== null )
  245. {
  246. // Check for conditions which will return no rows.
  247. if ( count( $actionTypes ) == 0 )
  248. return false;
  249. if ( count( $actionTypes ) == 1 )
  250. {
  251. $action = $actionTypes[0];
  252. $actionStr = $db->escapeString( $action );
  253. $conds[] = "action_type = '$actionStr'";
  254. }
  255. else
  256. {
  257. $actions = array();
  258. foreach ( $actionTypes as $action )
  259. {
  260. $actions[] = "'" . $db->escapeString( $action ) . "'";
  261. }
  262. $conds[] = "action_type IN (" . join( ", ", $actions ) . ")";
  263. }
  264. }
  265. $conds[] = 'is_original = 1';
  266. if ( $this->type == 'name' )
  267. {
  268. $conds[] = 'is_alias = 0';
  269. }
  270. else if ( $this->type == 'alias' )
  271. {
  272. $conds[] = 'is_alias = 1';
  273. }
  274. else // 'all'
  275. {
  276. }
  277. return "FROM ezurlalias_ml WHERE " . join( " AND ", $conds );
  278. }
  279. /*!
  280. \static
  281. Takes an array with database data in $row and turns them into eZPathElement objects.
  282. Entries which have multiple languages will be turned into multiple objects.
  283. */
  284. static public function makeList( $rows )
  285. {
  286. if ( !is_array( $rows ) || count( $rows ) == 0 )
  287. return array();
  288. $list = array();
  289. $maxNumberOfLanguages = eZContentLanguage::maxCount();
  290. foreach ( $rows as $row )
  291. {
  292. $row['always_available'] = $row['lang_mask'] % 2;
  293. $mask = $row['lang_mask'] & ~1;
  294. for ( $i = 1; $i < $maxNumberOfLanguages; ++$i )
  295. {
  296. $newMask = (1 << $i);
  297. if ( ($newMask & $mask) > 0 )
  298. {
  299. $row['lang_mask'] = (1 << $i);
  300. $list[] = $row;
  301. }
  302. }
  303. }
  304. $objectList = eZPersistentObject::handleRows( $list, 'eZPathElement', true );
  305. return $objectList;
  306. }
  307. }
  308. ?>