PageRenderTime 6ms CodeModel.GetById 3ms app.highlight 51ms RepoModel.GetById 1ms app.codeStats 0ms

/AIT/ItemType.php

https://github.com/touv/ait
PHP | 894 lines | 549 code | 99 blank | 246 comment | 116 complexity | ab96f2ed35bdc3b88239f2449616a1d3 MD5 | raw file
  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/**
 26 * @category  AIT
 27 * @package   AIT
 28 * @author    Nicolas Thouvenin <nthouvenin@gmail.com>
 29 * @copyright 2009 Nicolas Thouvenin
 30 * @license   http://opensource.org/licenses/lgpl-license.php LGPL
 31 * @version   SVN: $Id$
 32 * @link      http://ait.touv.fr/
 33 */
 34
 35/**
 36 * Dépendances
 37 */
 38require_once 'AIT.php';
 39require_once 'AIT/Item.php';
 40require_once 'AIT/TagType.php';
 41
 42
 43/**
 44 * Représente un TYPE d'ITEM
 45 *
 46 * @category  AIT
 47 * @package   AIT
 48 * @author    Nicolas Thouvenin <nthouvenin@gmail.com>
 49 * @copyright 2009 Nicolas Thouvenin
 50 * @license   http://opensource.org/licenses/lgpl-license.php LGPL
 51 * @link      http://ait.touv.fr/
 52 */
 53class AIT_ItemType extends AIT
 54{
 55    private $TagTypes = array();
 56    // {{{ __construct
 57    /**
 58     * Constructeur
 59     *
 60     * @param string $label nom du tupe d'item
 61     * @param PDOAIT $pdo objet de connexion à la base
 62     * @param integer $id Identifiant système de l'élement (si déjà connu).
 63     * @param array $row Propriétés de l'élément (si déja connu)
 64     */
 65    function __construct($l, PDOAIT $pdo, $id = false, $row = false)
 66    {
 67        parent::__construct($pdo, 'ItemType');
 68
 69        if (!is_string($l) and !is_null($l) and $id !== false)
 70            trigger_error('Argument 1 passed to '.__METHOD__.' must be a string, '.gettype($l).' given', E_USER_ERROR);
 71        if ($id !== false && !is_int($id))
 72            trigger_error('Argument 3 passed to '.__METHOD__.' must be a integer, '.gettype($id).' given', E_USER_ERROR);
 73        if ($row !== false && !is_array($row))
 74            trigger_error('Argument 4 passed to '.__METHOD__.' must be a Array, '.gettype($row).' given', E_USER_ERROR);
 75
 76
 77        $this->_label = $l;
 78        $this->_type  = self::ITEM;
 79        if ($id === false) {
 80            $this->_id = $this->_addTag($this->_label, $this->_type, $row);
 81            $this->callClassCallback('addHook', $this);
 82
 83            if ($row !== false)
 84                foreach($this->_cols as $n => $t)
 85                    if (isset($row[$n]))
 86                        $this->_set($n, $row[$n]);
 87        }
 88        else {
 89            if ($row !== false) $this->_fill($row);
 90            $this->_id = (int) $id;
 91            if (is_null($this->_label)) {
 92                $r = $this->_getTagBySystemID($id);
 93                $this->_label = $r['label'];
 94            }
 95        }
 96    }
 97    // }}}
 98
 99    // {{{ addTagType
100    /**
101     * Ajout d'un type de tag au type d'item courant
102     *
103     * @param string $l label
104     *
105     * @return AIT_TagType
106     */
107    function addTagType($l, $r = false)
108    {
109        if (!is_string($l))
110            trigger_error('Argument 1 passed to '.__METHOD__.' must be a String, '.gettype($l).' given', E_USER_ERROR);
111
112        return new AIT_TagType($l, $this->_id, $this->getPDO(), false, $r);
113    }
114    function addTag($l, $r = false) { return $this->addTagType($l, $r); }
115    // }}}
116
117    // {{{ getTagType
118    /**
119     * Récupére un type de tag du type d'item courant
120     *
121     * @param string $l label
122     *
123     * @return AIT_TagType
124     */
125    function getTagType($l)
126    {
127        if (!is_string($l))
128            trigger_error('Argument 1 passed to '.__METHOD__.' must be a String, '.gettype($l).' given', E_USER_ERROR);
129
130        $sql = sprintf('
131            SELECT tag.id id, label, type
132            FROM %s tag
133            LEFT JOIN %s b ON tag.id=b.tag_id
134            WHERE label = ? and type = %s and item_id = ?
135            LIMIT 0,1
136            ',
137            $this->getPDO()->tag(),
138            $this->getPDO()->tagged(),
139            self::TAG
140        );
141        self::timer();
142        $stmt = $this->getPDO()->prepare($sql);
143        $stmt->bindParam(1, $l, PDO::PARAM_STR);
144        $stmt->bindParam(2, $this->_id, PDO::PARAM_INT);
145        $stmt->execute();
146        settype($this->_id, 'integer');
147        if (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
148            if (is_null($row['id'])) continue;
149            settype($row['type'], 'integer');
150            settype($row['id'], 'integer');
151            $ret = new AIT_TagType($row['label'], $this->_id, $this->getPDO(), $row['id'], $row);
152        }
153        else $ret = null;
154        $stmt->closeCursor();
155        self::debug(self::timer(true), $sql, $l, $this->_id);
156
157        return $ret;
158    }
159    function getTag($l) { return $this->getTagType($l); }
160    // }}}
161
162    // {{{ defTagType
163    /**
164     * Récupére un type tag associé au type d'item courant.
165     * Si le tag n'existe pas il est automatiquement créé.
166     *
167     * @param string $l nom du tag
168     *
169     * @return AIT_TagType
170     */
171    function defTagType($l)
172    {
173        $ret = $this->getTagType($l);
174        if (is_null($ret)) {
175            $ret = new AIT_TagType($l, $this->_id, $this->getPDO());
176        }
177        return $ret;
178    }
179    function defTag($l) { return $this->defTagType($l); }
180    // }}}
181
182    // {{{ getTagTypes
183    /**
184     * Récupére tout les types de tags de l'item courant
185     *
186     * @param integer $offset décalage à parir du premier enregistrement
187     * @param integer $lines nombre de lignes à retourner
188     * @param integer $ordering flag permettant le tri
189     * @param array   $cols filtre sur les champs complémentaires
190     *
191     * @return AITResult
192     */
193    function getTagTypes($offset = null, $lines = null, $ordering = null, $cols = array())
194    {
195        if (!is_null($offset) && !is_int($offset))
196            trigger_error('Argument 1 passed to '.__METHOD__.' must be a integer, '.gettype($offset).' given', E_USER_ERROR);
197        if (!is_null($lines) && !is_int($lines))
198            trigger_error('Argument 2 passed to '.__METHOD__.' must be a integer, '.gettype($lines).' given', E_USER_ERROR);
199        if (!is_null($ordering) && !is_int($ordering))
200            trigger_error('Argument 3 passed to '.__METHOD__.' must be a integer, '.gettype($ordering).' given', E_USER_ERROR);
201        if (!is_array($cols))
202            trigger_error('Argument 4 passed to '.__METHOD__.' must be a array'.gettype($cols).' given', E_USER_ERROR);
203
204
205        $sql1 = 'SELECT id, label, prefix, suffix, buffer, scheme, language, score, frequency, type, content ';
206        $sql2 = sprintf('
207            FROM %1$s tagged
208            LEFT JOIN %2$s tag ON tagged.tag_id=tag.id
209            LEFT JOIN %3$s dat ON tag.dat_hash=dat.hash
210            WHERE item_id = ?
211            ',
212            $this->getPDO()->tagged(),
213            $this->getPDO()->tag(),
214            $this->getPDO()->dat()
215        );
216        $sql = $sql1.$sql2.$this->filter($cols);
217        self::sqler($sql, $offset, $lines, $ordering);
218
219        if (($r = $this->callClassCallback(
220            'getTagTypesCache',
221            $cid = self::str2cid($sql, $this->_id)
222        )) !== false) return $r;
223
224        self::timer();
225        $stmt = $this->getPDO()->prepare($sql);
226        $stmt->bindParam(1, $this->_id, PDO::PARAM_INT);
227        $stmt->execute();
228        settype($this->_id, 'integer');
229        $ret = array();
230        while (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
231            if (is_null($row['id'])) continue;
232            settype($row['id'], 'integer');
233            $ret[] = new AIT_TagType($row['label'], $this->_id, $this->getPDO(), $row['id'], $row);
234        }
235        $stmt->closeCursor();
236        self::debug(self::timer(true), $sql, $this->_id);
237
238        $sql = 'SELECT COUNT(*) '.$sql2;
239        $r = new AITResult($ret);
240        $r->setQueryForTotal($sql, array($this->_id => PDO::PARAM_INT,), $this->getPDO());
241
242        if (isset($cid))
243            $this->callClassCallback('getTagTypesCache', $cid, $r);
244
245        return $r;
246    }
247    function getTags($offset = null, $lines = null, $ordering = null) { return $this->getTagTypes($offset, $lines, $ordering); }
248    // }}}
249
250    // {{{ countTagTypes
251    /**
252     * Compte le nombre de tags associés au type d'item courant
253     *
254     * @return integer
255     */
256    function countTagTypes()
257    {
258        try {
259            $sql = sprintf('
260                SELECT count(*)
261                FROM %s tagged
262                WHERE item_id = ?
263                ',
264                $this->getPDO()->tagged()
265            );
266
267            self::timer();
268            $stmt = $this->getPDO()->prepare($sql);
269            $stmt->bindParam(1, $this->_id, PDO::PARAM_INT);
270            $stmt->execute();
271            settype($this->_id, 'integer');
272
273            $c = (int)$stmt->fetchColumn(0);
274            $stmt->closeCursor();
275            self::debug(self::timer(true), $sql, $this->_id);
276
277            return $c;
278        }
279        catch (PDOException $e) {
280            self::catchError($e);
281        }
282    }
283    function countTags() { return $this->countTagTypes(); }
284    // }}}
285
286    // {{{ newItem
287    /**
288     * Crée un item son label étant calculé automatiquement
289     *
290     * @return AIT_Item
291     */
292    function newItem()
293    {
294        $o = new AIT_Item('NEW', $this->_id, $this->getPDO());
295        $o->ren('#'.$o->getSystemID());
296        return $o;
297    }
298    // }}}
299
300    // {{{ addItem
301    /**
302     * Ajout d'un item au type d'item courant
303     *
304     * @param string $l nom du nouveau item
305     *
306     * @return AIT_Item
307     */
308    function addItem($l, $r = false)
309    {
310        if (!is_string($l))
311            trigger_error('Argument 1 passed to '.__METHOD__.' must be a String, '.gettype($l).' given', E_USER_ERROR);
312
313        return new AIT_Item($l, $this->_id, $this->getPDO(), false, $r);
314    }
315    // }}}
316
317    // {{{ getItem
318    /**
319     * Récupère un item
320     *
321     * @param string $l nom de l'item
322     *
323     * @return AIT_Item
324     */
325    function getItem($l)
326    {
327        if (!is_string($l))
328            trigger_error('Argument 1 passed to '.__METHOD__.' must be a String, '.gettype($l).' given', E_USER_ERROR);
329
330        $sql = sprintf('
331            SELECT id, label, type
332            FROM %s tag
333            WHERE label = ? AND type = ?
334            LIMIT 0,1
335            ',
336            $this->getPDO()->tag()
337        );
338
339        if (($r = $this->callClassCallback(
340            'getItemCache',
341            $cid = self::str2cid($l, $this->_id)
342        )) !== false) return $r;
343
344
345        self::timer();
346        $stmt = $this->getPDO()->prepare($sql);
347        $stmt->bindParam(1, $l, PDO::PARAM_STR);
348        $stmt->bindParam(2, $this->_id, PDO::PARAM_INT);
349        $stmt->execute();
350        settype($this->_id, 'integer');
351        if (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
352            if (is_null($row['id'])) continue;
353            settype($row['type'], 'integer');
354            settype($row['id'], 'integer');
355            $ret = new AIT_Item($row['label'], $this->_id, $this->getPDO(), $row['id'], $row);
356        }
357        else $ret = null;
358
359        $id = (int)$stmt->fetchColumn(0);
360        $stmt->closeCursor();
361        self::debug(self::timer(true), $sql, $l, $this->_id);
362
363        if (isset($cid))
364            $this->callClassCallback('getItemCache', $cid, $ret);
365
366        return $ret;
367    }
368    // }}}
369
370    // {{{ defItem
371    /**
372     * Récupére un item associé au type d'item courant.
373     * Si l'item n'existe pas il est automatiquement créé.
374     *
375     * @param string $l nom de l'item
376     *
377     * @return AIT_Item
378     */
379    function defItem($l)
380    {
381        $ret = $this->getItem($l);
382        if (is_null($ret))
383            $ret = new AIT_Item($l, $this->_id, $this->getPDO());
384        return $ret;
385    }
386    // }}}
387
388    // {{{ getItems
389    /**
390     * Récupére tous les items du type d'item courant
391     *
392     * @param integer $offset décalage à parir du premier enregistrement
393     * @param integer $lines nombre de lignes à retourner
394     * @param integer $ordering flag permettant le tri
395     * @param array   $cols filtre sur les champs complémentaires
396     *
397     * @return AITResult
398     */
399    function getItems($offset = null, $lines = null, $ordering = null, $cols = array())
400    {
401        if (!is_null($offset) && !is_int($offset))
402            trigger_error('Argument 1 passed to '.__METHOD__.' must be a integer, '.gettype($offset).' given', E_USER_ERROR);
403        if (!is_null($lines) && !is_int($lines))
404            trigger_error('Argument 2 passed to '.__METHOD__.' must be a integer, '.gettype($offset).' given', E_USER_ERROR);
405        if (!is_null($ordering) && !is_int($ordering))
406            trigger_error('Argument 3 passed to '.__METHOD__.' must be a integer, '.gettype($ordering).' given', E_USER_ERROR);
407        if (!is_array($cols))
408            trigger_error('Argument 4 passed to '.__METHOD__.' must be a array'.gettype($cols).' given', E_USER_ERROR);
409
410
411        $sql1 = 'SELECT id, label, prefix, suffix, buffer, scheme, language, score, frequency, content ';
412        $sql2 = sprintf('
413            FROM %s tag
414            LEFT JOIN %s dat ON tag.dat_hash=dat.hash
415            WHERE type = ?
416            ',
417            $this->getPDO()->tag(),
418            $this->getPDO()->dat()
419        );
420        $sql = $sql1.$sql2.$this->filter($cols);
421        self::sqler($sql, $offset, $lines, $ordering);
422
423        if (($r = $this->callClassCallback(
424            'getItemsCache',
425            $cid = self::str2cid($sql, $this->_id)
426        )) !== false) return $r;
427
428        self::timer();
429        $stmt = $this->getPDO()->prepare($sql);
430        $stmt->bindParam(1, $this->_id, PDO::PARAM_INT);
431        $stmt->execute();
432        settype($this->_id, 'integer');
433        $ret = array();
434        while (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
435            if (is_null($row['id'])) continue;
436            settype($row['id'], 'integer');
437            $ret[] = new AIT_Item($row['label'], $this->_id, $this->getPDO(), $row['id'], $row);
438        }
439        $stmt->closeCursor();
440        self::debug(self::timer(true), $sql, $this->_id);
441
442        $sql = 'SELECT COUNT(*) '.$sql2;
443        $r = new AITResult($ret);
444        $r->setQueryForTotal($sql, array($this->_id => PDO::PARAM_INT,), $this->getPDO());
445
446        if (isset($cid))
447            $this->callClassCallback('getItemsCache', $cid, $r);
448
449        return $r;
450    }
451    // }}}
452
453    // {{{ fetchItems
454    /**
455     * Récupére les items possédant un ou plusieurs tags donnée en paramètres
456     *
457     * @param ArrayObject $tags Tableau de tag
458     * @param integer $offset décalage à parir du premier enregistrement
459     * @param integer $lines nombre de lignes à retourner
460     * @param integer $ordering flag permettant le tri
461     * @param array   $cols filtre sur les champs complémentaires
462     *
463     * @return	AITResult
464     */
465    function fetchItems(ArrayObject $tags, $offset = null, $lines = null, $ordering = null, $cols = array())
466    {
467        if (!is_null($offset) && !is_int($offset))
468            trigger_error('Argument 2 passed to '.__METHOD__.' must be a integer, '.gettype($offset).' given', E_USER_ERROR);
469        if (!is_null($lines) && !is_int($lines))
470            trigger_error('Argument 3 passed to '.__METHOD__.' must be a integer, '.gettype($lines).' given', E_USER_ERROR);
471        if (!is_null($ordering) && !is_int($ordering))
472            trigger_error('Argument 4 passed to '.__METHOD__.' must be a integer, '.gettype($ordering).' given', E_USER_ERROR);
473        if (!is_array($cols))
474            trigger_error('Argument 4 passed to '.__METHOD__.' must be a array'.gettype($cols).' given', E_USER_ERROR);
475
476
477        $n = 0;
478        $w  = '';
479        if ($tags->count() == 0) return new AITResult(array());
480        foreach($tags as $tag) {
481            if (! $tag instanceof AIT_Tag) {
482                trigger_error('Line #'.($n + 1).' of Argument 1 passed to '.__METHOD__.' must be a instance of AIT_Tag, '.gettype($tag).' given and ignored', E_USER_NOTICE);
483                continue;
484            }
485            if (empty($w)) {
486                $w .= sprintf(' tagged.tag_id = %s ', $tag->getSystemID());
487            }
488            else {
489                $w .= sprintf(' AND EXISTS (SELECT null FROM %s t WHERE t.item_id = tagged.item_id and t.tag_id = %s)',
490                    $this->getPDO()->tagged(),
491                    $tag->getSystemID()
492                );
493            }
494            $n++;
495        }
496        if ($n === 0) return new AITResult(array());
497
498        $sql1 = 'SELECT DISTINCT id, label, prefix, suffix, buffer, scheme, language, score, frequency, type, content ';
499        $sql2 = sprintf('
500            FROM %s tagged
501            LEFT JOIN %s tag ON tagged.item_id = tag.id
502            LEFT JOIN %s dat ON tag.dat_hash=dat.hash
503            WHERE %s AND type = ?
504            ',
505            $this->getPDO()->tagged(),
506            $this->getPDO()->tag(),
507            $this->getPDO()->dat(),
508            $w
509        );
510        $sql = $sql1.$sql2.$this->filter($cols);
511        self::sqler($sql, $offset, $lines, $ordering);
512
513        if (($r = $this->callClassCallback(
514            'fetchItemsCache',
515            $cid = self::str2cid($sql, $this->_id)
516        )) !== false) return $r;
517
518        self::timer();
519        $stmt = $this->getPDO()->prepare($sql);
520        $stmt->bindParam(1, $this->_id, PDO::PARAM_INT);
521        $stmt->execute();
522        settype($this->_id, 'integer');
523        $ret = array();
524        while (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
525            if (is_null($row['id'])) continue;
526            settype($row['type'], 'integer');
527            settype($row['id'], 'integer');
528            $ret[] = new AIT_Item($row['label'], $row['type'], $this->getPDO(), $row['id'], $row);
529        }
530        $stmt->closeCursor();
531        self::debug(self::timer(true), $sql, $this->_id);
532
533        $sql = 'SELECT count(DISTINCT id) '.$sql2;
534        $r = new AITResult($ret, $this->getPDO());
535        if ($tags->count() > 1) {
536            $r->setQueryForTotal($sql, array($this->_id => PDO::PARAM_INT,));
537        }
538        else {
539            // Pour un seul tag il est intule de faire un "count"
540            // alors que sa frequence contient le nombre exacte d'items
541            $r->setTotal($tags->offsetGet(0)->countItems());
542        }
543        if (isset($cid))
544            $this->callClassCallback('fetchItemsCache', $cid, $r);
545
546        return $r;
547    }
548    // }}}
549
550    // {{{ searchItems
551    /**
552     * Recherche des items du type courant à partir des tags
553     *
554     * Important : Ne sont ramenés que des items possédant des tags.
555     *
556     * @param string  $query requete (le format dépend de la search_callback) sans callback c'est du SQL
557     * @param integer $offset décalage à parir du premier enregistrement
558     * @param integer $lines nombre de lignes à retourner
559     * @param integer $ordering flag permettant le tri
560     * @param array   $cols filtre sur les champs complémentaires
561     *
562     * @return AITResult
563     */
564    function searchItems($query, $offset = null, $lines = null, $ordering = null, $cols = array())
565    {
566        if (!is_null($offset) && !is_int($offset))
567            trigger_error('Argument 2 passed to '.__METHOD__.' must be a integer, '.gettype($offset).' given', E_USER_ERROR);
568        if (!is_null($lines) && !is_int($lines))
569            trigger_error('Argument 3 passed to '.__METHOD__.' must be a integer, '.gettype($lines).' given', E_USER_ERROR);
570        if (!is_null($ordering) && !is_int($ordering))
571            trigger_error('Argument 4 passed to '.__METHOD__.' must be a integer, '.gettype($ordering).' given', E_USER_ERROR);
572        if (!is_array($cols))
573            trigger_error('Argument 5 passed to '.__METHOD__.' must be a array'.gettype($cols).' given', E_USER_ERROR);
574
575
576        if ($this->isClassCallback('searchItemsHook'))
577            $query = $this->callClassCallback('searchItemsHook', $query, $this);
578
579        if ($query !== '' and $query !== false) $query = 'AND '.$query;
580        $sql1 = 'SELECT DISTINCT item.id id, item.label label, item.prefix prefix, item.suffix suffix, item.buffer buffer, item.scheme scheme, item.language language, item.score score, item.frequency frequency, content';
581        $sql2 = sprintf('
582            FROM %1$s tag
583            LEFT JOIN %2$s b ON tag.type=b.tag_id
584            LEFT JOIN %2$s d ON tag.id=d.tag_id
585            LEFT JOIN %1$s item ON d.item_id=item.id
586            LEFT JOIN %3$s dat ON tag.dat_hash=dat.hash
587            WHERE b.item_id = item.type AND item.type = ? %4$s
588            ',
589            $this->getPDO()->tag(),
590            $this->getPDO()->tagged(),
591            $this->getPDO()->dat(),
592            $query
593        );
594        $sql = $sql1.$sql2.$this->filter($cols);
595
596        self::sqler($sql, $offset, $lines, $ordering);
597
598        if (($r = $this->callClassCallback(
599            'searchItemsCache',
600            $cid = self::str2cid($sql, $this->_id)
601        )) !== false) return $r;
602
603        self::timer();
604
605        $stmt = $this->getPDO()->prepare($sql);
606        $stmt->bindParam(1, $this->_id, PDO::PARAM_INT);
607        $stmt->execute();
608        settype($this->_id, 'integer');
609        $ret = array();
610        while (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
611            if (is_null($row['id'])) continue;
612            settype($row['id'], 'integer');
613            $ret[] = new AIT_Item($row['label'], $this->_id, $this->getPDO(), $row['id'], $row);
614        }
615        $stmt->closeCursor();
616        self::debug(self::timer(true), $sql, $this->_id);
617
618        $sql = 'SELECT COUNT(DISTINCT item.id) '.$sql2;
619        $r = new AITResult($ret);
620        $r->setQueryForTotal($sql, array($this->_id => PDO::PARAM_INT,), $this->getPDO());
621
622        if (isset($cid))
623            $this->callClassCallback('searchItemsCache', $cid, $r);
624
625        return $r;
626    }
627    // }}}
628
629    // {{{ getItemBySystemID
630    /**
631     * Récupère un Item
632     *
633     * @param integer $i
634     *
635     * @return AIT_Item
636     */
637    function getItemBySystemID($i)
638    {
639        if (!is_integer($i))
640            trigger_error('Argument 1 passed to '.__METHOD__.' must be a integer, '.gettype($i).' given', E_USER_ERROR);
641
642        $row = $this->_getTagBySystemID($i);
643        if (is_array($row)) {
644            return new AIT_Item($row['label'], $this->_id, $this->getPDO(), $row['id']);
645        }
646    }
647    // }}}
648
649    // {{{ queryItems
650    /**
651     * On recherche des items associés au TYPE d'ITEM courant à partir d'un objet AITQuery
652     *
653     * @param AITQuery $query requete
654     * @param integer $offset décalage à parir du premier enregistrement
655     * @param integer $lines nombre de lignes à retourner
656     * @param integer $ordering flag permettant le tri
657     * @param array   $cols filtre sur les champs complémentaires
658     *
659     * @return	AITResult
660     */
661    function queryItems(AITQuery $query, $offset = null, $lines = null, $ordering = null, $cols = array())
662    {
663        if (!is_null($offset) && !is_int($offset))
664            trigger_error('Argument 2 passed to '.__METHOD__.' must be a integer, '.gettype($offset).' given', E_USER_ERROR);
665        if (!is_null($lines) && !is_int($lines))
666            trigger_error('Argument 3 passed to '.__METHOD__.' must be a integer, '.gettype($lines).' given', E_USER_ERROR);
667        if (!is_null($ordering) && !is_int($ordering))
668            trigger_error('Argument 4 passed to '.__METHOD__.' must be a integer, '.gettype($ordering).' given', E_USER_ERROR);
669        if (!is_array($cols))
670            trigger_error('Argument 4 passed to '.__METHOD__.' must be a array'.gettype($cols).' given', E_USER_ERROR);
671
672
673        $w = $query->getSQL();
674        $sql1 = 'SELECT id, label, prefix, suffix, buffer, scheme, language, score, frequency, type, content ';
675        $sql2 = sprintf('
676            FROM (%s) temp
677            LEFT JOIN %s tag ON temp.item_id = tag.id
678            LEFT JOIN %s dat ON tag.dat_hash=dat.hash
679            WHERE type = ?
680            ',
681            $w,
682            $this->getPDO()->tag(),
683            $this->getPDO()->dat()
684        );
685        $sql = $sql1.$sql2.$this->filter($cols);
686        self::sqler($sql, $offset, $lines, $ordering);
687
688        if (($r = $this->callClassCallback(
689            'queryItemsCache',
690            $cid = self::str2cid($sql, $this->_id)
691        )) !== false) return $r;
692
693        self::timer();
694        $stmt = $this->getPDO()->prepare($sql);
695        $stmt->bindParam(1, $this->_id, PDO::PARAM_INT);
696        $stmt->execute();
697        settype($this->_id, 'integer');
698        $ret = array();
699        while (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
700            if (is_null($row['id'])) continue;
701            settype($row['type'], 'integer');
702            settype($row['id'], 'integer');
703            $ret[] = new AIT_Item($row['label'], $row['type'], $this->getPDO(), $row['id'], $row);
704        }
705        $stmt->closeCursor();
706        self::debug(self::timer(true), $sql, $this->_id);
707
708        $sql = 'SELECT COUNT(*) '.$sql2;
709        $r = new AITResult($ret);
710        $r->setQueryForTotal($sql, array($this->_id => PDO::PARAM_INT,), $this->getPDO());
711
712        if (isset($cid))
713            $this->callClassCallback('queryItemsCache', $cid, $r);
714
715        return $r;
716    }
717    // }}}
718
719    // {{{ getAll
720    /**
721     * Récupére Tous les types d'items de la base
722     *
723     * @param PDOAIT $pdo pointeur sur la base de données
724     * @param integer $offset décalage à parir du premier enregistrement
725     * @param integer $lines nombre de lignes à retourner
726     * @param integer $ordering flag permettant le tri
727     *
728     * @return	AITResult
729     */
730    static function getAll(PDOAIT $pdo, $offset = null, $lines = null, $ordering = null)
731    {
732        if (!is_null($offset) && !is_int($offset))
733            trigger_error('Argument 2 passed to '.__METHOD__.' must be a integer, '.gettype($offset).' given', E_USER_ERROR);
734        if (!is_null($lines) && !is_int($lines))
735            trigger_error('Argument 3 passed to '.__METHOD__.' must be a integer, '.gettype($lines).' given', E_USER_ERROR);
736        if (!is_null($ordering) && !is_int($ordering))
737            trigger_error('Argument 4 passed to '.__METHOD__.' must be a integer, '.gettype($ordering).' given', E_USER_ERROR);
738
739        $sql1 = 'SELECT id, label, prefix, suffix, buffer, scheme, language, score, frequency, content';
740        $sql2 = sprintf('
741            FROM %s tag
742            LEFT JOIN %s dat ON tag.dat_hash=dat.hash
743            WHERE type = 1
744            ',
745            $pdo->tag(),
746            $pdo->dat()
747        );
748        $sql = $sql1.$sql2;
749        self::sqler($sql, $offset, $lines, $ordering);
750        $stmt = $pdo->prepare($sql);
751        $stmt->execute();
752        $ret = array();
753        while (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
754            if (is_null($row['id'])) continue;
755            settype($row['type'], 'integer');
756            settype($row['id'], 'integer');
757            $ret[] = new AIT_ItemType($row['label'], $pdo, $row['id'], $row);
758        }
759        $stmt->closeCursor();
760
761        $sql = 'SELECT COUNT(*) '.$sql2;
762        $r = new AITResult($ret);
763        $r->setQueryForTotal($sql, array(), $pdo);
764
765        return $r;
766    }
767    // }}}
768
769    // {{{ countItems
770    /**
771     * Compte le nombre d'items du type d'item courant
772     *
773     * @return integer
774     */
775    function countItems()
776    {
777        return (int) $this->_get('frequency', true);
778    }
779    // }}}
780
781    // {{{ del
782    /**
783     * Suppression de l'élement courrant
784     */
785    public function del()
786    {
787        $items = $this->getItems();
788        foreach($items as $item) {
789            $item->del(true);
790        }
791        $tags = $this->getTags();
792        foreach($tags as $tag) {
793            $tag->del(true);
794        }
795        $this->_rmTag();
796    }
797    // }}}
798
799    // {{{ select
800    /**
801     * Selectionne des items du type courant à partir des items eux-même
802     *
803     * @param string  $query requete (le format dépend de la search_callback) sans callback c'est du SQL
804     * @param integer $offset décalage à parir du premier enregistrement
805     * @param integer $lines nombre de lignes à retourner
806     * @param integer $ordering flag permettant le tri
807     * @param array   $cols filtre sur les champs complémentaires
808     *
809     * @return AITResult
810     */
811    function selectItems($query, $offset = null, $lines = null, $ordering = null, $cols = array())
812    {
813        if (!is_null($offset) && !is_int($offset))
814            trigger_error('Argument 2 passed to '.__METHOD__.' must be a integer, '.gettype($offset).' given', E_USER_ERROR);
815        if (!is_null($lines) && !is_int($lines))
816            trigger_error('Argument 3 passed to '.__METHOD__.' must be a integer, '.gettype($lines).' given', E_USER_ERROR);
817        if (!is_null($ordering) && !is_int($ordering))
818            trigger_error('Argument 4 passed to '.__METHOD__.' must be a integer, '.gettype($ordering).' given', E_USER_ERROR);
819        if (!is_array($cols))
820            trigger_error('Argument 5 passed to '.__METHOD__.' must be a array'.gettype($cols).' given', E_USER_ERROR);
821
822
823        if ($this->isClassCallback('selectItemsHook'))
824            $query = $this->callClassCallback('selectItemsHook', $query, $this);
825
826        if ($query !== '' and $query !== false) $query = 'AND '.$query;
827        $sql1 = 'SELECT DISTINCT id, label, prefix, suffix, buffer, scheme, language, score, frequency, content';
828        $sql2 = sprintf('
829            FROM %1$s item 
830            LEFT JOIN %2$s dat ON item.dat_hash=dat.hash
831            WHERE item.type = ? %3$s
832            ',
833            $this->getPDO()->tag(),
834            $this->getPDO()->dat(),
835            $query
836        );
837        $sql = $sql1.$sql2.$this->filter($cols, 'item');
838
839        self::sqler($sql, $offset, $lines, $ordering);
840
841        if (($r = $this->callClassCallback(
842            'selectItemsCache',
843            $cid = self::str2cid($sql, $this->_id)
844        )) !== false) return $r;
845
846        self::timer();
847
848        $stmt = $this->getPDO()->prepare($sql);
849        $stmt->bindParam(1, $this->_id, PDO::PARAM_INT);
850        $stmt->execute();
851        settype($this->_id, 'integer');
852        $ret = array();
853        while (($row = $stmt->fetch(PDO::FETCH_ASSOC))) {
854            if (is_null($row['id'])) continue;
855            settype($row['id'], 'integer');
856            $ret[] = new AIT_Item($row['label'], $this->_id, $this->getPDO(), $row['id'], $row);
857        }
858        $stmt->closeCursor();
859        self::debug(self::timer(true), $sql, $this->_id, $this->_id);
860
861        $sql = 'SELECT COUNT(*) '.$sql2;
862        $r = new AITResult($ret);
863        $r->setQueryForTotal($sql, array($this->_id => PDO::PARAM_INT,), $this->getPDO());
864
865        if (isset($cid))
866            $this->callClassCallback('selectItemsCache', $cid, $r);
867
868        return $r;
869    }
870    // }}}
871
872    // {{{ __get
873    /**
874     * Retourne un type de tag associé
875     *
876     * @param string $name
877     *
878     * @return AIT_TypeTag
879     */
880    public function __get($name) {
881        if (is_null($name) or $name == '')
882            return null;
883        if (!isset($this->TagTypes[$name]))
884            $this->TagTypes[$name] = $this->defTag($name);
885
886        return $this->TagTypes[$name];
887    }
888    // }}}
889
890}
891
892
893
894