PageRenderTime 54ms CodeModel.GetById 25ms RepoModel.GetById 1ms app.codeStats 0ms

/AIT/TagType.php

https://github.com/touv/ait
PHP | 455 lines | 250 code | 46 blank | 159 comment | 52 complexity | 6c35517ac5b36fc7bfbd16df924bd3b1 MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. // vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4 encoding=utf-8 fdm=marker :
  3. // {{{ Licence
  4. // +--------------------------------------------------------------------------+
  5. // | AIT - All is Tag |
  6. // +--------------------------------------------------------------------------+
  7. // | Copyright (C) 2009 Nicolas Thouvenin |
  8. // +--------------------------------------------------------------------------+
  9. // | This library is free software; you can redistribute it and/or |
  10. // | modify it under the terms of the GNU General Public License |
  11. // | as published by the Free Software Foundation; either version 2 |
  12. // | of the License, or (at your option) any later version. |
  13. // | |
  14. // | This program is distributed in the hope that it will be useful, |
  15. // | but WITHOUT ANY WARRANTY; without even the implied warranty of |
  16. // | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
  17. // | General Public License for more details. |
  18. // | |
  19. // | You should have received a copy of the GNU General Public License |
  20. // | along with this library; if not, write to the Free Software |
  21. // | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
  22. // +--------------------------------------------------------------------------+
  23. // }}}
  24. /**
  25. * @category AIT
  26. * @package AIT
  27. * @author Nicolas Thouvenin <nthouvenin@gmail.com>
  28. * @copyright 2009 Nicolas Thouvenin
  29. * @license http://opensource.org/licenses/lgpl-license.php LGPL
  30. * @version SVN: $Id$
  31. * @link http://ait.touv.fr/
  32. */
  33. /**
  34. * Dépendances
  35. */
  36. require_once 'AIT.php';
  37. /**
  38. * Représente un TYPE de TAG
  39. *
  40. * @category AIT
  41. * @package AIT
  42. * @author Nicolas Thouvenin <nthouvenin@gmail.com>
  43. * @copyright 2009 Nicolas Thouvenin
  44. * @license http://opensource.org/licenses/lgpl-license.php LGPL
  45. * @link http://ait.touv.fr/
  46. */
  47. class AIT_TagType extends AIT
  48. {
  49. protected $_item_id;
  50. // {{{ __construct
  51. /**
  52. * Constructeur
  53. *
  54. * @param string $l nom du nouveau type de tag (label)
  55. * @param integer $i identifiant du type d'item
  56. * @param PDO $pdo objet de connexion à la base
  57. * @param integer $id identifiant physique de l'élement (si déjà connu)
  58. * @param array $row Propriétés de l'élément (si déja connu)
  59. */
  60. function __construct($l, $i, PDO $pdo, $id = false, $row = false)
  61. {
  62. parent::__construct($pdo, 'TagType');
  63. if (!is_string($l) and !is_null($l) and $id !== false)
  64. trigger_error('Argument 1 passed to '.__METHOD__.' must be a String, '.gettype($l).' given', E_USER_ERROR);
  65. if (!is_null($i) && !is_int($i))
  66. trigger_error('Argument 2 passed to '.__METHOD__.' must be a Integer, '.gettype($i).' given', E_USER_ERROR);
  67. if ($id !== false && !is_int($id))
  68. trigger_error('Argument 4 passed to '.__METHOD__.' must be a Integer, '.gettype($id).' given', E_USER_ERROR);
  69. if ($row !== false && !is_array($row))
  70. trigger_error('Argument 5 passed to '.__METHOD__.' must be a Array, '.gettype($row).' given', E_USER_ERROR);
  71. if (!empty($l) and !preg_match(',[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*,',$l))
  72. trigger_error('Argument 1 passed to '.__METHOD__.' must be compatible with PHP variable names , `'.$l.'` given', E_USER_ERROR);
  73. $this->_label = $l;
  74. $this->_type = 2;
  75. $this->_item_id = $i;
  76. if ($id === false) {
  77. if (! $this->_checkTag($this->_item_id, self::ITEM)) {
  78. trigger_error('Argument 2 passed to '.__METHOD__.' not describe a "tagtype"', E_USER_ERROR);
  79. }
  80. $this->_id = $this->_addTag($this->_label, 2, $row);
  81. $this->callClassCallback('addHook', $this);
  82. if ($row !== false)
  83. foreach($this->_cols as $n => $t)
  84. if (isset($row[$n]))
  85. $this->_set($n, $row[$n]);
  86. if ($this->_checkTagged($this->_id, $this->_item_id) === false) {
  87. $this->_addTagged($this->_id, $this->_item_id);
  88. // Ne Pas incrémenter la fréquence, car elle sert à compter le nombre d'items
  89. }
  90. }
  91. else {
  92. if ($row !== false) $this->_fill($row);
  93. $this->_id = (int) $id;
  94. if (is_null($this->_label)) {
  95. $r = $this->_getTagBySystemID($id);
  96. $this->_label = $r['label'];
  97. }
  98. }
  99. }
  100. // }}}
  101. // {{{ newTag
  102. /**
  103. * Crée un tag, son label étant calculé automatiquement
  104. *
  105. * @return AIT_Tag
  106. */
  107. function newTag()
  108. {
  109. $o = new AIT_Tag('NEW', $this->_id, null, $this->getPDO());
  110. $o->ren('#'.$o->getSystemID());
  111. return $o;
  112. }
  113. // }}}
  114. // {{{ addTag
  115. /**
  116. * Ajout d'un tag au type de tag courant
  117. *
  118. * @param string $l nom du nouveau item
  119. *
  120. * @return AIT_Item
  121. */
  122. function addTag($l, $r = false)
  123. {
  124. if (!is_string($l))
  125. trigger_error('Argument 1 passed to '.__METHOD__.' must be a string, '.gettype($l).' given', E_USER_ERROR);
  126. return new AIT_Tag($l, $this->_id, null, $this->getPDO(), false, $r);
  127. }
  128. // }}}
  129. // {{{ getTag
  130. /**
  131. * Récupère un tag
  132. *
  133. * @param string $l nom du tag
  134. *
  135. * @return AIT_Tag
  136. */
  137. function getTag($l)
  138. {
  139. if (!is_string($l))
  140. trigger_error('Argument 1 passed to '.__METHOD__.' must be a string, '.gettype($l).' given', E_USER_ERROR);
  141. $sql = sprintf('
  142. SELECT id, label, type
  143. FROM %s tag
  144. WHERE label = ? AND type = ?
  145. LIMIT 0,1
  146. ',
  147. $this->getPDO()->tag()
  148. );
  149. if (($r = $this->callClassCallback(
  150. 'getTagCache',
  151. $cid = self::str2cid($l, $this->_id)
  152. )) !== false) return $r;
  153. self::timer();
  154. $stmt = $this->getPDO()->prepare($sql);
  155. $stmt->bindParam(1, $l, PDO::PARAM_STR);
  156. $stmt->bindParam(2, $this->_id, PDO::PARAM_INT);
  157. $stmt->execute();
  158. settype($this->_id, 'integer');
  159. if (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
  160. if (is_null($row['id'])) continue;
  161. settype($row['type'], 'integer');
  162. settype($row['id'], 'integer');
  163. $ret = new AIT_Tag($row['label'], $row['type'], null, $this->getPDO(), $row['id'], $row);
  164. }
  165. else $ret = null;
  166. $stmt->closeCursor();
  167. self::debug(self::timer(true), $sql, $l, $this->_id);
  168. if (isset($cid))
  169. $this->callClassCallback('getTagCache', $cid, $ret);
  170. return $ret;
  171. }
  172. // }}}
  173. // {{{ defTag
  174. /**
  175. * Récupére un tag du type courant
  176. * Si le tag n'existe pas il est automatiquement créé.
  177. *
  178. * @param string $l nom du tag
  179. *
  180. * @return AIT_Tag
  181. */
  182. function defTag($l)
  183. {
  184. $ret = $this->getTag($l);
  185. if (is_null($ret))
  186. $ret = new AIT_Tag($l, $this->_id, null, $this->getPDO());
  187. return $ret;
  188. }
  189. // }}}
  190. // {{{ getTags
  191. /**
  192. * Récupére tous les tags du type de tag courant
  193. *
  194. * @param integer $offset décalage à parir du premier enregistrement
  195. * @param integer $lines nombre de lignes à retourner
  196. * @param integer $ordering flag permettant le tri
  197. * @param array $cols filtre sur les champs complémentaires
  198. *
  199. * @return AITResult
  200. */
  201. function getTags($offset = null, $lines = null, $ordering = null, $cols = array())
  202. {
  203. if (!is_null($offset) && !is_int($offset))
  204. trigger_error('Argument 1 passed to '.__METHOD__.' must be a integer, '.gettype($offset).' given', E_USER_ERROR);
  205. if (!is_null($lines) && !is_int($lines))
  206. trigger_error('Argument 2 passed to '.__METHOD__.' must be a integer, '.gettype($offset).' given', E_USER_ERROR);
  207. if (!is_null($ordering) && !is_int($ordering))
  208. trigger_error('Argument 3 passed to '.__METHOD__.' must be a integer, '.gettype($ordering).' given', E_USER_ERROR);
  209. if (!is_array($cols))
  210. trigger_error('Argument 4 passed to '.__METHOD__.' must be a array'.gettype($cols).' given', E_USER_ERROR);
  211. $sql1 = 'SELECT id, label, prefix, suffix, buffer, scheme, language, score, frequency, content';
  212. $sql2 = sprintf('
  213. FROM %s tag
  214. LEFT JOIN %s dat ON tag.dat_hash=dat.hash
  215. WHERE type = ?
  216. ',
  217. $this->getPDO()->tag(),
  218. $this->getPDO()->dat()
  219. );
  220. $sql = $sql1.$sql2.$this->filter($cols);
  221. self::sqler($sql, $offset, $lines, $ordering);
  222. if (($r = $this->callClassCallback(
  223. 'getTagsCache',
  224. $cid = self::str2cid($sql, $this->_id)
  225. )) !== false) return $r;
  226. self::timer();
  227. $stmt = $this->getPDO()->prepare($sql);
  228. $stmt->bindParam(1, $this->_id, PDO::PARAM_INT);
  229. $stmt->execute();
  230. settype($this->_id, 'integer');
  231. $ret = array();
  232. while (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
  233. if (is_null($row['id'])) continue;
  234. settype($row['id'], 'integer');
  235. $ret[] = new AIT_Tag($row['label'], $this->_id, null, $this->getPDO(), $row['id'], $row);
  236. }
  237. $stmt->closeCursor();
  238. self::debug(self::timer(true), $sql, $this->_id);
  239. $sql = 'SELECT COUNT(*) '.$sql2;
  240. $r = new AITResult($ret);
  241. $r->setQueryForTotal($sql, array($this->_id => PDO::PARAM_INT,), $this->getPDO());
  242. if (isset($cid))
  243. $this->callClassCallback('getTagsCache', $cid, $r);
  244. return $r;
  245. }
  246. // }}}
  247. // {{{ getTagBySystemID
  248. /**
  249. * Récupère un tag
  250. *
  251. * @param intger $i
  252. *
  253. * @return AIT_Item
  254. */
  255. function getTagBySystemID($i)
  256. {
  257. if (!is_integer($i))
  258. trigger_error('Argument 1 passed to '.__METHOD__.' must be a integer, '.gettype($i).' given', E_USER_ERROR);
  259. if (($r = $this->callClassCallback(
  260. 'getTagBySystemIDCache',
  261. $cid = self::str2cid($i)
  262. )) !== false) return $r;
  263. $row = $this->_getTagBySystemID($i);
  264. if (is_array($row)) {
  265. $r = new AIT_Tag($row['label'], $row['type'], null, $this->getPDO(), $i);
  266. if (isset($cid))
  267. $this->callClassCallback('getTagBySystemIDCache', $cid, $r);
  268. return $r;
  269. }
  270. }
  271. // }}}
  272. // {{{ searchTags
  273. /**
  274. * Recherche des tags du type courant
  275. *
  276. * @param string $query requete (le format dépend de la search_callback) sans callback c'est du SQL
  277. * @param integer $offset décalage à parir du premier enregistrement
  278. * @param integer $lines nombre de lignes à retourner
  279. * @param integer $ordering flag permettant le tri
  280. * @param array $cols filtre sur les champs complémentaires
  281. *
  282. * @return AITResult
  283. */
  284. function searchTags($query, $offset = null, $lines = null, $ordering = null, $cols = array())
  285. {
  286. if (!is_null($offset) && !is_int($offset))
  287. trigger_error('Argument 2 passed to '.__METHOD__.' must be a integer, '.gettype($offset).' given', E_USER_ERROR);
  288. if (!is_null($lines) && !is_int($lines))
  289. trigger_error('Argument 3 passed to '.__METHOD__.' must be a integer, '.gettype($lines).' given', E_USER_ERROR);
  290. if (!is_null($ordering) && !is_int($ordering))
  291. trigger_error('Argument 4 passed to '.__METHOD__.' must be a integer, '.gettype($ordering).' given', E_USER_ERROR);
  292. if (!is_array($cols))
  293. trigger_error('Argument 5 passed to '.__METHOD__.' must be a array'.gettype($cols).' given', E_USER_ERROR);
  294. if ($this->isClassCallback('searchTagsHook'))
  295. $query = $this->callClassCallback('searchTagsHook', $query, $this);
  296. if ($query !== '' and $query !== false) $query = 'AND '.$query;
  297. $sql1 = 'SELECT id, label, prefix, suffix, buffer, scheme, language, score, frequency, content';
  298. $sql2 = sprintf('
  299. FROM %1$s tag
  300. LEFT JOIN %2$s dat ON tag.dat_hash=dat.hash
  301. WHERE tag.type = ? %3$s
  302. ',
  303. $this->getPDO()->tag(),
  304. $this->getPDO()->dat(),
  305. $query
  306. );
  307. $sql = $sql1.$sql2.$this->filter($cols);
  308. self::sqler($sql, $offset, $lines, $ordering);
  309. self::timer();
  310. if (($r = $this->callClassCallback(
  311. 'searchTagsCache',
  312. $cid = self::str2cid($sql, $this->_id)
  313. )) !== false) return $r;
  314. $stmt = $this->getPDO()->prepare($sql);
  315. $stmt->bindParam(1, $this->_id, PDO::PARAM_INT);
  316. $stmt->execute();
  317. settype($this->_id, 'integer');
  318. $ret = array();
  319. while (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
  320. if (is_null($row['id'])) continue;
  321. settype($row['id'], 'integer');
  322. $ret[] = new AIT_Tag($row['label'], $this->_id, null, $this->getPDO(), $row['id'], $row);
  323. }
  324. $stmt->closeCursor();
  325. self::debug(self::timer(true), $sql, $this->_id, $this->_id);
  326. $sql = 'SELECT COUNT(*) '.$sql2;
  327. $r = new AITResult($ret);
  328. $r->setQueryForTotal($sql, array($this->_id => PDO::PARAM_INT,), $this->getPDO());
  329. if (isset($cid))
  330. $this->callClassCallback('searchTagsCache', $cid, $r);
  331. return $r;
  332. }
  333. // }}}
  334. // {{{ countTags
  335. /**
  336. * Compte le nombre de tags du type de tag courant
  337. *
  338. * @return integer
  339. */
  340. function countTags()
  341. {
  342. try {
  343. $sql = sprintf('
  344. SELECT count(*)
  345. FROM %s tag
  346. WHERE type = ?
  347. ',
  348. $this->getPDO()->tag()
  349. );
  350. self::timer();
  351. $stmt = $this->getPDO()->prepare($sql);
  352. $stmt->bindParam(1, $this->_id, PDO::PARAM_INT);
  353. $stmt->execute();
  354. settype($this->_id, 'integer');
  355. $c = (int)$stmt->fetchColumn(0);
  356. $stmt->closeCursor();
  357. self::debug(self::timer(true), $sql, $this->_id);
  358. return $c;
  359. }
  360. catch (PDOException $e) {
  361. self::catchError($e);
  362. }
  363. }
  364. // }}}
  365. // {{{ countItems
  366. /**
  367. * Compte le nombre d'item attaché au tag du 'type' de tag courant
  368. *
  369. * @param boolean $reload récupére la valeur en base et non celle du cache de l'objet
  370. *
  371. * @return integer
  372. */
  373. function countItems($reload = true)
  374. {
  375. return (int) $this->_get('frequency', $reload);
  376. }
  377. // }}}
  378. // {{{ del
  379. /**
  380. * Suppression de l'élement courrant
  381. */
  382. public function del($cascade = false)
  383. {
  384. $tags = $this->getTags();
  385. foreach($tags as $tag) {
  386. $tag->del($cascade);
  387. }
  388. $this->_rmTagged($this->_id, null);
  389. $this->_rmTag();
  390. }
  391. // }}}
  392. // {{{ selectTags
  393. /**
  394. * Selectionne des tags du type courant
  395. *
  396. * @param string $query requete (le format dépend de la search_callback) sans callback c'est du SQL
  397. * @param integer $offset décalage à parir du premier enregistrement
  398. * @param integer $lines nombre de lignes à retourner
  399. * @param integer $ordering flag permettant le tri
  400. * @param array $cols filtre sur les champs complémentaires
  401. *
  402. * @return AITResult
  403. */
  404. function selectTags($query, $offset = null, $lines = null, $ordering = null, $cols = array())
  405. {
  406. return $this->searchTags($query, $offset, $lines, $ordering, $cols);
  407. }
  408. // }}}
  409. }