source: extensions/GrumPluginClasses/classes/GPCRequestBuilder.class.inc.php @ 10246

Last change on this file since 10246 was 10246, checked in by grum, 13 years ago

bug:2149
Compatibility with Piwigo 2.2

File size: 43.6 KB
Line 
1<?php
2/* -----------------------------------------------------------------------------
3  class name: GCPRequestBuilder
4  class version  : 1.1.5
5  plugin version : 3.4.3
6  date           : 2010-09-08
7
8  ------------------------------------------------------------------------------
9  Author     : Grum
10    email    : grum@piwigo.org
11    website  : http://photos.grum.com
12    PWG user : http://forum.phpwebgallery.net/profile.php?id=3706
13
14    << May the Little SpaceFrog be with you ! >>
15  ------------------------------------------------------------------------------
16  *
17  * theses classes provides base functions to manage search pictures in the
18  * database
19  *
20  *
21  * HOW TO USE IT ?
22  * ===============
23  *
24  * when installing the plugin, you have to register the usage of the request
25  * builder
26  *
27  * 1/ Create a RBCallback class
28  *  - extends the GPCSearchCallback class ; the name of the extended class must
29  *    be "RBCallBack%" => replace the "%" by the plugin name
30  *     for example : 'ThePlugin' => 'RBCallBackThePlugin'
31  *
32  * 2/ In the plugin 'maintain.inc.php' file :
33  *  - function plugin_install, add :
34  *       GPCRequestBuilder::register('plugin name', 'path to the RBCallback classe');
35  *          for example : GPCRequestBuilder::register('ThePlugin', $piwigo_path.'plugins/ThePlugin/rbcallback_file_name.php');
36  *
37  *
38  *  - function plugin_uninstall, add :
39  *       GPCRequestBuilder::unregister('plugin name');
40  *          for example : GPCRequestBuilder::unregister('ThePlugin');
41  *
42  * 3/ In the plugin code, put somewhere
43  *     GPCRequestBuilder::loadJSandCSS();
44  *     => this will load specific JS and CSS in the page, by adding url in the
45  *        the header, so try to put this where you're used to prepare the header
46  *
47  * 4/ to display the request builder, just add the returned string in the html
48  *    page
49  *       $stringForTheTemplate=GPCRequestBuilder::displaySearchPage();
50  *
51  *
52  *
53  * HOW DOES THE REQUEST BUILDER WORKS ?
54  * ====================================
55  *
56  * the request builder works in 2 steps :
57  *  - first step  : build a cache, to associate all image id corresponding to
58  *                  the search criterion
59  *                  the cache is an association of request ID/image id
60  *  - second step : use the cache to retrieve images informations
61  *
62  ------------------------------------------------------------------------------
63  :: HISTORY
64
65| release | date       |
66| 1.0.0   | 2010/04/30 | * start coding
67|         |            |
68| 1.1.0   | 2010/09/08 | * add functionnalities to manage complex requests
69|         |            |
70| 1.1.1   | 2010/10/14 | * fix bug on the buildGroupRequest function
71|         |            |   . adding 'DISTINCT' keyword to the SQL requests
72|         |            |
73|         |            | * ajax management moved into the gpc_ajax.php file
74|         |            |
75|         |            | * fix bug on user level access to picture
76|         |            |
77| 1.1.2   | 2010/11/01 | * mantis bug:1984
78|         |            |   . RBuilder returns an error message when one picture
79|         |            |     have multiple categories
80|         |            |
81| 1.1.3   | 2011/01/31 | * mantis bug:2156
82|         |            |   . undefined variable on RBuilder screens
83|         |            |
84| 1.1.4   | 2011/01/31 | * mantis bug:2167
85|         |            |
86| 1.1.5   | 2011/04/10 | * Compatibility with piwigo 2.2
87|         |            |
88|         |            |
89|         |            |
90|         |            |
91|         |            |
92|         |            |
93
94  --------------------------------------------------------------------------- */
95
96if(!defined('GPC_DIR')) define('GPC_DIR' , baseName(dirname(dirname(__FILE__))));
97if(!defined('GPC_PATH')) define('GPC_PATH' , PHPWG_PLUGINS_PATH . GPC_DIR . '/');
98
99include_once('GPCTables.class.inc.php');
100
101/**
102 *
103 * Preparing the temporary table => doCache()
104 * ------------------------------------------
105 * To prepare the cache, the request builder use the following functions :
106 *  - getImageId
107 *  - getFrom
108 *  - getWhere
109 *  - getHaving
110 *
111 * Preparing the cache table => doCache()
112 * --------------------------------------
113 * To prepare the cache, the request builder use the following functions :
114 *  => the getFilter function is used to prepare the filter for the getPage()
115 *     function ; not used to build the cache
116 *
117 * Retrieving the results => getPage()
118 * -----------------------------------
119 * To retrieve the image informations, the request builder uses the following
120 * functions :
121 *  - getSelect
122 *  - getFrom
123 *  - getJoin
124 *  - getFilter (in fact, the result of this function is stored by the doCache()
125 *               function while the cache is builded, but it is used only when
126 *               retrieving the results for multirecord tables)
127 *  - formatData
128 *
129 *
130 * Example
131 * -------
132 * Consider the table "tableA" like this
133 *
134 *  - (*) imageId
135 *  - (*) localId
136 *  -     att1
137 *  -     att2
138 *  The primary key is the 'imageId'+'localId' attributes
139 *    => for one imageId, you can have ZERO or more than ONE record
140 *       when you register the class, you have to set the $multiRecord parameter
141 *       to 'y'
142 *
143 *  gatImageId returns      : "tableA.imageId"
144 *  getSelect returns       : "tableA.att1, tableA.att2"
145 *  getFrom returns         : "tableA"
146 *  getWhere returns        : "tableA.localId= xxxx AND tableA.att1 = zzzz"
147 *  getJoin returns         : "tableA.imageId = pit.id"
148 *  getFilter returns       : "tableA.localId= xxxx"
149 *
150 *  Examples :
151 *   - plugin AdvancedMetadata use getFilter
152 *   - plugin AdvancedSearchEngine, module ASETag use getHaving and getWhere
153 */
154class GPCSearchCallback {
155
156  /**
157   * the getImageId returns the name of the image id attribute
158   * return String
159   */
160  static public function getImageId()
161  {
162    return("");
163  }
164
165  /**
166   * the getSelect function must return an attribute list separated with a comma
167   *
168   * "att1, att2, att3, att4"
169   *
170   * you can specifie tables names and aliases
171   *
172   * "table1.att1 AS alias1, table1.att2 AS alias2, table2.att3 AS alias3"
173   */
174  static public function getSelect($param="")
175  {
176    return("");
177  }
178
179  /**
180   * the getFrom function must return a tables list separated with a comma
181   *
182   * "table1, (table2 left join table3 on table2.key = table3.key), table4"
183   */
184  static public function getFrom($param="")
185  {
186    return("");
187  }
188
189  /**
190   * the getWhere function must return a ready to use where clause
191   *
192   * "(att1 = value0 OR att2 = value1) AND att4 LIKE value2 "
193   */
194  static public function getWhere($param="")
195  {
196    return("");
197  }
198
199
200  /**
201   * the getHaving function return a ready to user HAVING clause
202   *
203   * " FIND_IN_SET(value0, GROUP_CONCAT(DISTINCT att1 SEPARATOR ',')) AND
204   *   FIND_IN_SET(value0, GROUP_CONCAT(DISTINCT att1 SEPARATOR ',')) "
205   *
206   */
207  static public function getHaving($param="")
208  {
209    return("");
210  }
211
212
213  /**
214   * the getJoin function must return a ready to use sql statement allowing to
215   * join the IMAGES table (key : pit.id) with given conditions
216   *
217   * "att3 = pit.id "
218   */
219  static public function getJoin($param="")
220  {
221    return("");
222  }
223
224
225  /**
226   * the getFilter function must return a ready to use where clause
227   * this where clause is used to filter the cache when the used tables can
228   * return more than one result
229   *
230   * the filter can be empty, can be equal to the where clause, or can be equal
231   * to a sub part of the where clause
232   *
233   * in most case, return "" is the best solution
234   *
235   */
236  static public function getFilter($param="")
237  {
238    //return(self::getWhere($param));
239    return("");
240  }
241
242
243  /**
244   * this function is called by the request builder, allowing to display plugin
245   * data with a specific format
246   *
247   * @param Array $attributes : array of ('attribute_name' => 'attribute_value')
248   * @return String : HTML formatted value
249   */
250  static public function formatData($attributes)
251  {
252    return(print_r($attributes, true));
253  }
254
255
256  /**
257   * this function is called by the request builder to make the search page, and
258   * must return the HTML & JS code of the dialogbox used to select criterion
259   *
260   * Notes :
261   *  - the dialogbox is a JS object with a public method 'show'
262   *  - when the method show is called, one parameter is given by the request
263   *    builder ; the parameter is an object defined as this :
264   *      {
265   *        cBuilder: an instance of the criteriaBuilder object used in the page,
266   *      }
267   *
268   *
269   *
270   *
271   * @param String $mode : can take 'admin' or 'public' values, allowing to
272   *                       return different interface if needed
273   * @return String : HTML formatted value
274   */
275  static public function getInterfaceContent($mode='admin')
276  {
277    return("");
278  }
279
280  /**
281   * this function returns the label displayed in the criterion menu
282   *
283   * @return String : label displayed in the criterions menu
284   */
285  static public function getInterfaceLabel()
286  {
287    return(l10n('gpc_rb_unknown_interface'));
288  }
289
290  /**
291   * this function returns the name of the dialog box class
292   *
293   * @return String : name of the dialogbox class
294   */
295  static public function getInterfaceDBClass()
296  {
297    return('');
298  }
299
300
301}
302
303
304//load_language('rbuilder.lang', GPC_PATH);
305
306
307class GPCRequestBuilder {
308
309  static public $pluginName = 'GPCRequestBuilder';
310  static public $version = '1.1.4';
311
312  static private $tables = Array();
313  static protected $tGlobalId=0;
314
315  /**
316   * register a plugin using GPCRequestBuilder
317   *
318   * @param String $pluginName : the plugin name
319   * @param String $fileName : the php filename where the callback function can
320   *                           be found
321   * @return Boolean : true if registering is Ok, otherwise false
322   */
323  static public function register($plugin, $fileName)
324  {
325    $config=Array();
326    if(!GPCCore::loadConfig(self::$pluginName, $config))
327    {
328      $config['registered']=array();
329    }
330
331    $config['registered'][$plugin]=Array(
332      'name' => $plugin,
333      'fileName' => $fileName,
334      'date' => date("Y-m-d H:i:s"),
335      'version' => self::$version
336    );
337    return(GPCCore::saveConfig(self::$pluginName, $config));
338  }
339
340  /**
341   * unregister a plugin using GPCRequestBuilder
342   *
343   * assume that if the plugin was not registerd before, unregistering returns
344   * a true value
345   *
346   * @param String $pluginName : the plugin name
347   * @return Boolean : true if registering is Ok, otherwise false
348   */
349  static public function unregister($plugin)
350  {
351    $config=Array();
352    if(GPCCore::loadConfig(self::$pluginName, $config))
353    {
354      if(array_key_exists('registered', $config))
355      {
356        if(array_key_exists($plugin, $config['registered']))
357        {
358          unset($config['registered'][$plugin]);
359          return(GPCCore::saveConfig(self::$pluginName, $config));
360        }
361      }
362    }
363    // assume if the plugin was not registered before, unregistering it is OK
364    return(true);
365  }
366
367  /**
368   * @return Array : list of registered plugins
369   */
370  static public function getRegistered()
371  {
372    $config=Array();
373    if(GPCCore::loadConfig(self::$pluginName, $config))
374    {
375      if(array_key_exists('registered', $config))
376      {
377        return($config['registered']);
378      }
379    }
380    return(Array());
381  }
382
383
384  /**
385   * initialise the class
386   *
387   * @param String $prefixeTable : the piwigo prefixe used on tables name
388   * @param String $pluginNameFile : the plugin name used for tables name
389   */
390  static public function init($prefixeTable, $pluginNameFile)
391  {
392    $list=Array('request', 'result_cache', 'temp');
393
394    for($i=0;$i<count($list);$i++)
395    {
396      self::$tables[$list[$i]]=$prefixeTable.$pluginNameFile.'_'.$list[$i];
397    }
398  }
399
400  /**
401   * create the tables needed by RequestBuilder (used during the gpc process install)
402   */
403  static public function createTables()
404  {
405    $tablesDef=array(
406"CREATE TABLE `".self::$tables['request']."` (
407  `id` int(10) unsigned NOT NULL auto_increment,
408  `user_id` int(10) unsigned NOT NULL,
409  `date` datetime NOT NULL,
410  `num_items` int(10) unsigned NOT NULL default '0',
411  `execution_time` float unsigned NOT NULL default '0',
412  `connected_plugin` char(255) NOT NULL,
413  `filter` text NOT NULL,
414  `parameters` text NOT NULL,
415  PRIMARY KEY  (`id`)
416)
417CHARACTER SET utf8 COLLATE utf8_general_ci",
418
419"CREATE TABLE `".self::$tables['result_cache']."` (
420  `id` int(10) unsigned NOT NULL,
421  `image_id` int(10) unsigned NOT NULL,
422  PRIMARY KEY  (`id`,`image_id`)
423)
424CHARACTER SET utf8 COLLATE utf8_general_ci",
425
426"CREATE TABLE `".self::$tables['temp']."` (
427  `requestId` char(30) NOT NULL,
428  `imageId` mediumint(8) unsigned NOT NULL,
429  PRIMARY KEY  (`requestId`,`imageId`)
430)
431CHARACTER SET utf8 COLLATE utf8_general_ci",
432  );
433
434    $tablef= new GPCTables(self::$tables);
435    $tablef->create($tablesDef);
436
437    return(true);
438  }
439
440  /**
441   * update the tables needed by RequestBuilder (used during the gpc process
442   * activation)
443   */
444  static public function updateTables($pluginPreviousRelease)
445  {
446    $tablef=new GPCTables(array(self::$tables['temp']));
447
448    switch($pluginPreviousRelease)
449    {
450      case '03.01.00':
451        $tablesCreate=array();
452        $tablesUpdate=array();
453
454        $tablesCreate[]=
455"CREATE TABLE `".self::$tables['temp']."` (
456  `requestId` char(30) NOT NULL,
457  `imageId` mediumint(8) unsigned NOT NULL,
458  PRIMARY KEY  (`requestId`,`imageId`)
459)
460CHARACTER SET utf8 COLLATE utf8_general_ci";
461
462        $tablesUpdate[self::$tables['request']]['filter']=
463"ADD COLUMN  `filter` text NOT NULL default '' ";
464
465
466
467        $tablef->create($tablesCreate);
468        $tablef->updateTablesFields($tablesUpdate);
469        // no break ! need to be updated like the next release
470        // break;
471      case '03.01.01':
472      case '03.02.00':
473      case '03.02.01':
474      case '03.03.00':
475      case '03.03.01':
476        $tablesUpdate=array();
477
478        $tablesUpdate[self::$tables['request']]['parameters']=
479"ADD COLUMN `parameters` TEXT NOT NULL AFTER `filter`";
480
481        $tablef->updateTablesFields($tablesUpdate);
482        // no break ! need to be updated like the next release
483        // break;
484    }
485
486    return(true);
487  }
488
489  /**
490   * delete the tables needed by RequestBuilder
491   */
492  static public function deleteTables()
493  {
494    $tablef= new GPCTables(self::$tables);
495    $tablef->drop();
496    return(true);
497  }
498
499
500  /**
501   * delete the config
502   */
503  static public function deleteConfig()
504  {
505    GPCCore::deleteConfig(self::$pluginName);
506  }
507
508  /**
509   * this function add and handler on the 'loc_end_page_header' to add request
510   * builder JS script & specific CSS on the page
511   *
512   * use it when the displayed page need an access to the criteriaBuilder GUI
513   *
514   */
515  static public function loadJSandCSS()
516  {
517    load_language('rbuilder.lang', GPC_PATH);
518    add_event_handler('loc_begin_page_header', array('GPCRequestBuilder', 'insertJSandCSSFiles'), 9);
519  }
520
521
522  /**
523   * insert JS a CSS file in header
524   *
525   * the function is declared public because it used by the 'loc_begin_page_header'
526   * event callback
527   *
528   * DO NOT USE IT DIRECTLY
529   *
530   */
531  static public function insertJSandCSSFiles()
532  {
533    global $template;
534
535
536    $baseName=basename(dirname(dirname(__FILE__))).'/css/';
537    $template->append('head_elements', '<link href="plugins/'.$baseName.'rbuilder.css" type="text/css" rel="stylesheet"/>');
538    if(defined('IN_ADMIN')) $template->append('head_elements', '<link href="plugins/'.$baseName.'rbuilder_'.$template->get_themeconf('name').'.css" type="text/css" rel="stylesheet"/>');
539
540
541    $baseName=basename(dirname(dirname(__FILE__))).'/js/';
542    GPCCore::addHeaderJS('jquery', 'themes/default/js/jquery.min.js');
543    GPCCore::addHeaderJS('gpc.interface', 'plugins/'.$baseName.'external/interface/interface.js', array('jquery'));
544    GPCCore::addHeaderJS('gpc.inestedsortable', 'plugins/'.$baseName.'external/inestedsortable.pack.js', array('jquery', 'gpc.interface'));
545    GPCCore::addHeaderJS('gpc.rbCriteriaBuilder', 'plugins/'.$baseName.'rbCriteriaBuilder'.GPCCore::getMinified().'.js', array('gpc.inestedsortable'));
546
547    $template->append('head_elements',
548"<script type=\"text/javascript\">
549  requestBuilderOptions = {
550    textAND:\"".l10n('gpc_rb_textAND')."\",
551    textOR:\"".l10n('gpc_rb_textOR')."\",
552    textNoCriteria:\"".l10n('There is no criteria ! At least, one criteria is required to do search...')."\",
553    textSomethingWrong:\"".l10n('gpc_something_is_wrong_on_the_server_side')."\",
554    textCaddieUpdated:\"".l10n('gpc_the_caddie_is_updated')."\",
555    helpEdit:\"".l10n('gpc_help_edit_criteria')."\",
556    helpDelete:\"".l10n('gpc_help_delete_criteria')."\",
557    helpMove:\"".l10n('gpc_help_move_criteria')."\",
558    helpSwitchCondition:\"".l10n('gpc_help_switch_condition')."\",
559    ajaxUrl:'plugins/GrumPluginClasses/gpc_ajax.php',
560  }
561</script>");
562  }
563
564
565  /**
566   * execute request from the ajax call
567   *
568   * @return String : a ready to use HTML code
569   */
570  static public function executeRequest($ajaxfct)
571  {
572    $result='';
573    switch($ajaxfct)
574    {
575      case 'public.rbuilder.searchExecute':
576        $result=self::doCache();
577        break;
578      case 'public.rbuilder.searchGetPage':
579        $result=self::getPage($_REQUEST['requestNumber'], $_REQUEST['page'], $_REQUEST['numPerPage']);
580        break;
581    }
582    return($result);
583  }
584
585
586  /**
587   * clear the cache table
588   *
589   * @param Boolean $clearAll : if set to true, clear all records without
590   *                            checking timestamp
591   */
592  static public function clearCache($clearAll=false)
593  {
594    if($clearAll)
595    {
596      $sql="DELETE FROM ".self::$tables['result_cache'];
597    }
598    else
599    {
600      $sql="DELETE pgrc FROM ".self::$tables['result_cache']." pgrc
601              LEFT JOIN ".self::$tables['request']." pgr
602                ON pgrc.id = pgr.id
603              WHERE pgr.date < '".date('Y-m-d H:i:s', strtotime("-2 hour"))."'";
604    }
605    pwg_query($sql);
606  }
607
608  /**
609   * prepare the temporary table used for multirecord requests
610   *
611   * @param Integer $requestNumber : id of request
612   * @return String : name of the request key temporary table
613   */
614  static private function prepareTempTable($requestNumber)
615  {
616    //$tableName=call_user_func(Array('RBCallBack'.$plugin, 'getFrom'));
617    //$imageIdName=call_user_func(Array('RBCallBack'.$plugin, 'getImageId'));
618
619    $tempClauses=array();
620    foreach($_REQUEST['extraData'] as $key => $extraData)
621    {
622      $tempClauses[$key]=array(
623        'plugin' => $extraData['owner'],
624        'where' => call_user_func(Array('RBCallBack'.$extraData['owner'], 'getWhere'), $extraData['param']),
625        'having' => call_user_func(Array('RBCallBack'.$extraData['owner'], 'getHaving'), $extraData['param']),
626      );
627    }
628
629    $sql="INSERT INTO ".self::$tables['temp']." ".self::buildGroupRequest($_REQUEST[$_REQUEST['requestName']], $tempClauses, $_REQUEST['operator'], ' AND ', $requestNumber);
630//echo $sql;
631    $result=pwg_query($sql);
632
633    return($requestNumber);
634  }
635
636  /**
637   * clear the temporary table used for multirecord requests
638   *
639   * @param Array $requestNumber : the requestNumber to delete
640   */
641  static private function clearTempTable($requestNumber)
642  {
643    $sql="DELETE FROM ".self::$tables['temp']." WHERE requestId = '$requestNumber';";
644    pwg_query($sql);
645  }
646
647
648  /**
649   * execute a query, and place result in cache
650   *
651   *
652   * @return String : queryNumber;numberOfItems
653   */
654  static private function doCache()
655  {
656    global $user;
657
658    self::clearCache();
659
660    $registeredPlugin=self::getRegistered();
661    $requestNumber=self::getNewRequest($user['id']);
662
663    $build=Array(
664      'SELECT' => 'pit.id',
665      'FROM' => '',
666      'WHERE' => 'pit.level <= '.$user['level'],
667      'GROUPBY' => '',
668      'FILTER' => ''
669    );
670    $tmpBuild=Array(
671      'FROM' => Array(
672        '('.IMAGES_TABLE.' pit LEFT JOIN '.IMAGE_CATEGORY_TABLE.' pic ON pit.id = pic.image_id)' /*JOIN IMAGES & IMAGE_CATEGORY tables*/
673       .'   JOIN '.USER_CACHE_CATEGORIES_TABLE.' pucc ON pucc.cat_id=pic.category_id',  /* IMAGE_CATEGORY & USER_CACHE_CATEGORIES_TABLE tables*/
674
675      ),
676      'WHERE' => Array(),
677      'JOIN' => Array(999=>'pucc.user_id='.$user['id']),
678      'GROUPBY' => Array(
679        'pit.id'
680      ),
681      'FILTER' => Array(),
682    );
683
684    /* build data request for plugins
685     *
686     * Array('Plugin1' =>
687     *          Array(
688     *            criteriaNumber1 => pluginParam1,
689     *            criteriaNumber2 => pluginParam2,
690     *            criteriaNumberN => pluginParamN
691     *          ),
692     *       'Plugin2' =>
693     *          Array(
694     *            criteriaNumber1 => pluginParam1,
695     *            criteriaNumber2 => pluginParam2,
696     *            criteriaNumberN => pluginParamN
697     *          )
698     * )
699     *
700     */
701    $pluginNeeded=Array();
702    $pluginList=Array();
703    $tempName=Array();
704    foreach($_REQUEST['extraData'] as $key => $val)
705    {
706      $pluginNeeded[$val['owner']][$key]=$_REQUEST['extraData'][$key]['param'];
707      $pluginList[$val['owner']]=$val['owner'];
708    }
709
710    /* for each plugin, include the rb callback class file */
711    foreach($pluginList as $val)
712    {
713      if(file_exists($registeredPlugin[$val]['fileName']))
714      {
715        include_once($registeredPlugin[$val]['fileName']);
716      }
717    }
718
719    /* prepare the temp table for the request */
720    self::prepareTempTable($requestNumber);
721    $tmpBuild['FROM'][]=self::$tables['temp'];
722    $tmpBuild['JOIN'][]=self::$tables['temp'].".requestId = '".$requestNumber."'
723                        AND ".self::$tables['temp'].".imageId = pit.id";
724
725    /* for each needed plugin, prepare the filter */
726    foreach($pluginNeeded as $key => $val)
727    {
728      foreach($val as $itemNumber => $param)
729      {
730        $tmpFilter=call_user_func(Array('RBCallBack'.$key, 'getFilter'), $param);
731
732        if(trim($tmpFilter)!="") $tmpBuild['FILTER'][$key][]='('.$tmpFilter.')';
733      }
734    }
735
736
737    /* build FROM
738     *
739     */
740    $build['FROM']=implode(',', $tmpBuild['FROM']);
741    unset($tmpBuild['FROM']);
742
743    /* build WHERE
744     */
745    self::cleanArray($tmpBuild['WHERE']);
746    if(count($tmpBuild['WHERE'])>0)
747    {
748      $build['WHERE']=' ('.self::buildGroup($_REQUEST[$_REQUEST['requestName']], $tmpBuild['WHERE'], $_REQUEST['operator'], ' AND ').') ';
749    }
750    unset($tmpBuild['WHERE']);
751
752
753    /* build FILTER
754     */
755    self::cleanArray($tmpBuild['FILTER']);
756    if(count($tmpBuild['FILTER'])>0)
757    {
758      $tmp=array();
759      foreach($tmpBuild['FILTER'] as $key=>$val)
760      {
761        $tmp[$key]='('.implode(' OR ', $val).')';
762      }
763      $build['FILTER']=' ('.implode(' AND ', $tmp).') ';
764    }
765    unset($tmpBuild['FILTER']);
766
767
768    /* for each plugin, adds jointure with the IMAGE table
769     */
770    self::cleanArray($tmpBuild['JOIN']);
771    if(count($tmpBuild['JOIN'])>0)
772    {
773      if($build['WHERE']!='') $build['WHERE'].=' AND ';
774      $build['WHERE'].=' ('.implode(' AND ', $tmpBuild['JOIN']).') ';
775    }
776    unset($tmpBuild['JOIN']);
777
778    self::cleanArray($tmpBuild['GROUPBY']);
779    if(count($tmpBuild['GROUPBY'])>0)
780    {
781      $build['GROUPBY'].=' '.implode(', ', $tmpBuild['GROUPBY']).' ';
782    }
783    unset($tmpBuild['GROUPBY']);
784
785
786
787    $sql=' FROM '.$build['FROM'];
788    if($build['WHERE']!='')
789    {
790      $sql.=' WHERE '.$build['WHERE'];
791    }
792    if($build['GROUPBY']!='')
793    {
794      $sql.=' GROUP BY '.$build['GROUPBY'];
795    }
796
797    $sql.=" ORDER BY pit.id ";
798
799    $sql="INSERT INTO ".self::$tables['result_cache']." (SELECT DISTINCT $requestNumber, ".$build['SELECT']." $sql)";
800
801//echo $sql;
802    $returned="0;0";
803
804    $result=pwg_query($sql);
805    if($result)
806    {
807      $numberItems=pwg_db_changes($result);
808      self::updateRequest($requestNumber, $numberItems, 0, implode(',', $pluginList), $build['FILTER'], $_REQUEST['extraData']);
809
810      $returned="$requestNumber;".$numberItems;
811    }
812
813    self::clearTempTable($requestNumber);
814
815    return($returned);
816  }
817
818  /**
819   * return a page content. use the cache table to find request result
820   *
821   * @param Integer $requestNumber : the request number (from cache table)
822   * @param Integer $pageNumber : the page to be returned
823   * @param Integer $numPerPage : the number of items returned on a page
824   * @param String $mode : if mode = 'count', the function returns the number of
825   *                       rows ; otherwise, returns rows in a html string
826   * @return String : formatted HTML code
827   */
828  static private function getPage($requestNumber, $pageNumber, $numPerPage)
829  {
830    global $conf, $user;
831    $request=self::getRequest($requestNumber);
832
833    if($request===false)
834    {
835      return("KO");
836    }
837
838    $limitFrom=$numPerPage*($pageNumber-1);
839
840    $pluginNeeded=explode(',', $request['connected_plugin']);
841    $registeredPlugin=self::getRegistered();
842
843    $build=Array(
844      'SELECT' => '',
845      'FROM' => '',
846      'WHERE' => '',
847      'GROUPBY' => '',
848    );
849    $tmpBuild=Array(
850      'SELECT' => Array(
851        'RB_PIT' => "pit.id AS imageId, pit.name AS imageName, pit.path AS imagePath", // from the piwigo's image table
852        'RB_PIC' => "GROUP_CONCAT( pic.category_id SEPARATOR ',') AS imageCategoriesId",     // from the piwigo's image_category table
853        'RB_PCT' => "GROUP_CONCAT( CASE WHEN pct.name IS NULL THEN '' ELSE pct.name END SEPARATOR '#sep#') AS imageCategoriesNames,
854                     GROUP_CONCAT( CASE WHEN pct.permalink IS NULL THEN '' ELSE pct.permalink END SEPARATOR '#sep#') AS imageCategoriesPLink,
855                     GROUP_CONCAT( CASE WHEN pct.dir IS NULL THEN 'V' ELSE 'P' END) AS imageCategoriesDir",   //from the piwigo's categories table
856      ),
857      'FROM' => Array(
858        // join rb result_cache table with piwigo's images table, joined with the piwigo's image_category table, joined with the categories table
859        'RB' => "(((".self::$tables['result_cache']." pgrc
860                  RIGHT JOIN ".IMAGES_TABLE." pit
861                  ON pgrc.image_id = pit.id)
862                    RIGHT JOIN ".IMAGE_CATEGORY_TABLE." pic
863                    ON pit.id = pic.image_id)
864                       RIGHT JOIN ".CATEGORIES_TABLE." pct
865                       ON pct.id = pic.category_id)
866                          RIGHT JOIN ".USER_CACHE_CATEGORIES_TABLE." pucc
867                          ON pucc.cat_id = pic.category_id",
868      ),
869      'WHERE' => Array(
870        'RB' => "pgrc.id=".$requestNumber." AND pucc.user_id=".$user['id'],
871        ),
872      'JOIN' => Array(),
873      'GROUPBY' => Array(
874        'RB' => "pit.id"
875      )
876    );
877
878
879    $extraData=array();
880    foreach($request['parameters'] as $data)
881    {
882      $extraData[$data['owner']]=$data['param'];
883    }
884
885    /* for each needed plugin :
886     *  - include the file
887     *  - call the static public function getFrom, getJoin, getSelect
888     */
889    foreach($pluginNeeded as $key => $val)
890    {
891      if(array_key_exists($val, $registeredPlugin))
892      {
893        if(file_exists($registeredPlugin[$val]['fileName']))
894        {
895          include_once($registeredPlugin[$val]['fileName']);
896
897          $tmp=explode(',', call_user_func(Array('RBCallBack'.$val, 'getSelect'), $extraData[$val]));
898          foreach($tmp as $key2=>$val2)
899          {
900            $tmp[$key2]=self::groupConcatAlias($val2, '#sep#');
901          }
902          $tmpBuild['SELECT'][$val]=implode(',', $tmp);
903          $tmpBuild['FROM'][$val]=call_user_func(Array('RBCallBack'.$val, 'getFrom'), $extraData[$val]);
904          $tmpBuild['JOIN'][$val]=call_user_func(Array('RBCallBack'.$val, 'getJoin'), $extraData[$val]);
905        }
906      }
907    }
908
909    /* build SELECT
910     *
911     */
912    $build['SELECT']=implode(',', $tmpBuild['SELECT']);
913
914    /* build FROM
915     *
916     */
917    $build['FROM']=implode(',', $tmpBuild['FROM']);
918    unset($tmpBuild['FROM']);
919
920
921    /* build WHERE
922     */
923    if($request['filter']!='') $tmpBuild['WHERE'][]=$request['filter'];
924    $build['WHERE']=implode(' AND ', $tmpBuild['WHERE']);
925    unset($tmpBuild['WHERE']);
926
927    /* for each plugin, adds jointure with the IMAGE table
928     */
929    self::cleanArray($tmpBuild['JOIN']);
930    if(count($tmpBuild['JOIN'])>0)
931    {
932      $build['WHERE'].=' AND ('.implode(' AND ', $tmpBuild['JOIN']).') ';
933    }
934    unset($tmpBuild['JOIN']);
935
936    self::cleanArray($tmpBuild['GROUPBY']);
937    if(count($tmpBuild['GROUPBY'])>0)
938    {
939      $build['GROUPBY'].=' '.implode(', ', $tmpBuild['GROUPBY']).' ';
940    }
941    unset($tmpBuild['GROUPBY']);
942
943
944    $imagesList=Array();
945
946    $sql='SELECT DISTINCT '.$build['SELECT']
947        .' FROM '.$build['FROM']
948        .' WHERE '.$build['WHERE']
949        .' GROUP BY '.$build['GROUPBY'];
950
951    $sql.=' ORDER BY pit.id '
952         .' LIMIT '.$limitFrom.', '.$numPerPage;
953
954//echo $sql;
955    $result=pwg_query($sql);
956    if($result)
957    {
958      while($row=pwg_db_fetch_assoc($result))
959      {
960        // affect standard datas
961        $datas['imageThumbnail']=dirname($row['imagePath'])."/".$conf['dir_thumbnail']."/".$conf['prefix_thumbnail'].basename($row['imagePath']);
962        $datas['imageId']=$row['imageId'];
963        $datas['imagePath']=$row['imagePath'];
964        $datas['imageName']=$row['imageName'];
965
966        $datas['imageCategoriesId']=explode(',', $row['imageCategoriesId']);
967        $datas['imageCategoriesNames']=explode('#sep#', $row['imageCategoriesNames']);
968        $datas['imageCategoriesPLink']=explode('#sep#', $row['imageCategoriesPLink']);
969        $datas['imageCategoriesDir']=explode(',', $row['imageCategoriesDir']);
970
971        $datas['imageCategories']=Array();
972        for($i=0;$i<count($datas['imageCategoriesId']);$i++)
973        {
974          $datas['imageCategories'][]=array(
975            'id' => $datas['imageCategoriesId'][$i],
976            'name' => $datas['imageCategoriesNames'][$i],
977            'dirType' => $datas['imageCategoriesDir'][$i],
978            'pLinks' => $datas['imageCategoriesPLink'][$i],
979            'link'=> make_picture_url(
980                        array(
981                          'image_id' => $datas['imageId'],
982                          'category' => array
983                            (
984                              'id' => $datas['imageCategoriesId'][$i],
985                              'name' => $datas['imageCategoriesNames'][$i],
986                              'permalink' => $datas['imageCategoriesPLink'][$i]
987                            )
988                        )
989                      )
990          );
991        }
992
993        /* affect datas for each plugin
994         *
995         * each plugin have to format the data in an HTML code
996         *
997         * so, for each plugin :
998         *  - look the attributes given in the SELECT clause
999         *  - for each attributes, associate the returned value of the record
1000         *  - affect in datas an index equals to the plugin pluginName, with returned HTML code ; HTML code is get from a formatData function
1001         *
1002         * Example :
1003         *  plugin ColorStart provide 2 attributes 'csColors' and 'csColorsPct'
1004         *
1005         *  we affect to the $attributes var :
1006         *  $attributes['csColors'] = $row['csColors'];
1007         *  $attributes['csColorsPct'] = $row['csColorsPct'];
1008         *
1009         *  call the ColorStat RB callback formatData with the $attributes => the function return a HTML code ready to use in the template
1010         *
1011         *  affect $datas['ColorStat'] = $the_returned_html_code;
1012         *
1013         *
1014         */
1015        foreach($tmpBuild['SELECT'] as $key => $val)
1016        {
1017          if($key!='RB_PIT' && $key!='RB_PIC' && $key!='RB_PCT')
1018          {
1019            $tmp=explode(',', $val);
1020
1021            $attributes=Array();
1022
1023            foreach($tmp as $key2 => $val2)
1024            {
1025              $name=self::getAttribute($val2);
1026              $attributes[$name]=$row[$name];
1027            }
1028
1029            $datas['plugin'][$key]=call_user_func(Array('RBCallBack'.$key, 'formatData'), $attributes);
1030
1031            unset($tmp);
1032            unset($attributes);
1033          }
1034        }
1035        $imagesList[]=$datas;
1036        unset($datas);
1037      }
1038    }
1039
1040    return(self::toHtml($imagesList));
1041    //return("get page : $requestNumber, $pageNumber, $numPerPage<br>$debug<br>$sql");
1042  }
1043
1044  /**
1045   * remove all empty value from an array
1046   * @param Array a$array : the array to clean
1047   */
1048  static private function cleanArray(&$array)
1049  {
1050    foreach($array as $key => $val)
1051    {
1052      if(is_array($val))
1053      {
1054        self::cleanArray($val);
1055        if(count($val)==0) unset($array[$key]);
1056      }
1057      elseif(trim($val)=='') unset($array[$key]);
1058    }
1059  }
1060
1061  /**
1062   * returns the alias for an attribute
1063   *
1064   *  item1                          => returns item1
1065   *  table1.item1                   => returns item1
1066   *  table1.item1 AS alias1         => returns alias1
1067   *  item1 AS alias1                => returns alias1
1068   *  GROUP_CONCAT( .... ) AS alias1 => returns alias1
1069   *
1070   * @param String $var : value to examine
1071   * @return String : the attribute name
1072   */
1073  static private function getAttribute($val)
1074  {
1075    preg_match('/(?:GROUP_CONCAT\(.*\)|(?:[A-Z0-9_]*)\.)?([A-Z0-9_]*)(?:\s+AS\s+([A-Z0-9_]*))?/i', trim($val), $result);
1076    if(array_key_exists(2, $result))
1077    {
1078      return($result[2]);
1079    }
1080    elseif(array_key_exists(1, $result))
1081    {
1082      return($result[1]);
1083    }
1084    else
1085    {
1086      return($val);
1087    }
1088  }
1089
1090
1091  /**
1092   * returns a a sql statement GROUP_CONCAT for an alias
1093   *
1094   *  item1                  => returns GROUP_CONCAT(item1 SEPARATOR $sep) AS item1
1095   *  table1.item1           => returns GROUP_CONCAT(table1.item1 SEPARATOR $sep) AS item1
1096   *  table1.item1 AS alias1 => returns GROUP_CONCAT(table1.item1 SEPARATOR $sep) AS alias1
1097   *  item1 AS alias1        => returns GROUP_CONCAT(item1 SEPARATOR $sep) AS alias1
1098   *
1099   * @param String $val : value to examine
1100   * @param String $sep : the separator
1101   * @return String : the attribute name
1102   */
1103  static private function groupConcatAlias($val, $sep=',')
1104  {
1105    /*
1106     * table1.item1 AS alias1
1107     *
1108     * $result[3] = alias1
1109     * $result[2] = item1
1110     * $result[1] = table1.item1
1111     */
1112    preg_match('/((?:(?:[A-Z0-9_]*)\.)?([A-Z0-9_]*))(?:\s+AS\s+([A-Z0-9_]*))?/i', trim($val), $result);
1113    if(array_key_exists(3, $result))
1114    {
1115      return("GROUP_CONCAT(DISTINCT ".$result[1]." SEPARATOR '$sep') AS ".$result[3]);
1116    }
1117    elseif(array_key_exists(2, $result))
1118    {
1119      return("GROUP_CONCAT(DISTINCT ".$result[1]." SEPARATOR '$sep') AS ".$result[2]);
1120    }
1121    else
1122    {
1123      return("GROUP_CONCAT(DISTINCT $val SEPARATOR '$sep') AS ".$val);
1124    }
1125  }
1126
1127
1128  /**
1129   * get a new request number and create it in the request table
1130   *
1131   * @param Integer $userId : id of the user
1132   * @return Integer : the new request number, -1 if something wrong appened
1133   */
1134  static private function getNewRequest($userId)
1135  {
1136    $sql="INSERT INTO ".self::$tables['request']." VALUES('', '$userId', '".date('Y-m-d H:i:s')."', 0, 0, '', '', '')";
1137    $result=pwg_query($sql);
1138    if($result)
1139    {
1140      return(pwg_db_insert_id());
1141    }
1142    return(-1);
1143  }
1144
1145  /**
1146   * update request properties
1147   *
1148   * @param Integer $request_id : the id of request to update
1149   * @param Integer $numItems : number of items found in the request
1150   * @param Float $executionTime : time in second to execute the request
1151   * @param String $pluginList : list of used plugins
1152   * @param String $parameters : parameters given for the request
1153   * @return Boolean : true if request was updated, otherwise false
1154   */
1155  static private function updateRequest($requestId, $numItems, $executionTime, $pluginList, $additionalFilter, $parameters)
1156  {
1157    $sql="UPDATE ".self::$tables['request']."
1158            SET num_items = $numItems,
1159                execution_time = $executionTime,
1160                connected_plugin = '$pluginList',
1161                filter = '".mysql_escape_string($additionalFilter)."',
1162                parameters = '".serialize($parameters)."'
1163            WHERE id = $requestId";
1164    $result=pwg_query($sql);
1165    if($result)
1166    {
1167      return(true);
1168    }
1169    return(false);
1170  }
1171
1172  /**
1173   * returns request properties
1174   *
1175   * @param Integer $request_id : the id of request to update
1176   * @return Array : properties for request, false if request doesn't exist
1177   */
1178  static private function getRequest($requestId)
1179  {
1180    $returned=false;
1181    $sql="SELECT user_id, date, num_items, execution_time, connected_plugin, filter, parameters
1182          FROM ".self::$tables['request']."
1183          WHERE id = $requestId";
1184    $result=pwg_query($sql);
1185    if($result)
1186    {
1187      while($row=pwg_db_fetch_assoc($result))
1188      {
1189        if($row['parameters']!='') $row['parameters']=unserialize($row['parameters']);
1190        $returned=$row;
1191      }
1192    }
1193    return($returned);
1194  }
1195
1196
1197  /**
1198   * internal function used by the executeRequest function for single record
1199   * requests
1200   *
1201   * this function is called recursively
1202   *
1203   * @param Array $groupContent :
1204   * @param Array $items :
1205   * @return String : a where clause
1206   */
1207  static private function buildGroup($groupContent, $items, $groups, $operator)
1208  {
1209    $returned=Array();
1210    foreach($groupContent as $key => $val)
1211    {
1212      if(strpos($val['id'], 'iCbGroup')!==false)
1213      {
1214        preg_match('/[0-9]*$/i', $val['id'], $groupNumber);
1215        $returned[]=self::buildGroup($val['children'], $items, $groups, $groups[$groupNumber[0]]);
1216      }
1217      else
1218      {
1219        preg_match('/[0-9]*$/i', $val['id'], $itemNumber);
1220        $returned[]=" (".$items[$itemNumber[0]].") ";
1221      }
1222    }
1223    return('('.implode($operator, $returned).')');
1224  }
1225
1226
1227  /**
1228   * internal function used by the executeRequest function for multi records
1229   * requests
1230   *
1231   * this function is called recursively
1232   *
1233   * @param Array $groupContent :
1234   * @param Array $clausesItems : array with 'where' and 'having' conditions (and 'plugin' for the plugin)
1235   * @param Array $groups : operators of each group
1236   * @param String $operator : 'OR' or 'AND', according with the current group operator
1237   * @param String $requestNumber : the request number
1238   * @return String : part of a SQL request
1239   */
1240  static private function buildGroupRequest($groupContent, $clausesItems, $groups, $operator, $requestNumber)
1241  {
1242    $returnedS='';
1243    $returned=Array();
1244    foreach($groupContent as $key => $val)
1245    {
1246      if(strpos($val['id'], 'iCbGroup')!==false)
1247      {
1248        preg_match('/[0-9]*$/i', $val['id'], $groupNumber);
1249
1250        $groupValue=self::buildGroupRequest($val['children'], $clausesItems, $groups, $groups[$groupNumber[0]], $requestNumber);
1251
1252        if($groupValue!='')
1253          $returned[]=array(
1254            'mode'  => 'group',
1255            'value' => $groupValue
1256          );
1257      }
1258      else
1259      {
1260        preg_match('/[0-9]*$/i', $val['id'], $itemNumber);
1261
1262        $returned[]=array(
1263          'mode'  => 'item',
1264          'plugin' => $clausesItems[$itemNumber[0]]['plugin'],
1265          'valueWhere' => ($clausesItems[$itemNumber[0]]['where']!='')?" (".$clausesItems[$itemNumber[0]]['where'].") ":'',
1266          'valueHaving' => ($clausesItems[$itemNumber[0]]['having'])?" (".$clausesItems[$itemNumber[0]]['having'].") ":'',
1267        );
1268      }
1269    }
1270
1271    if(count($returned)>0)
1272    {
1273      if(strtolower(trim($operator))=='and')
1274      {
1275        $tId=0;
1276        foreach($returned as $key=>$val)
1277        {
1278          if($tId>0) $returnedS.=" JOIN ";
1279
1280          if($val['mode']=='item')
1281          {
1282            $returnedS.="(SELECT DISTINCT ".call_user_func(Array('RBCallBack'.$val['plugin'], 'getImageId'))." AS imageId
1283                          FROM ".call_user_func(Array('RBCallBack'.$val['plugin'], 'getFrom'));
1284            if($val['valueWhere']!='') $returnedS.=" WHERE ".$val['valueWhere'];
1285            if($val['valueHaving']!='')
1286              $returnedS.=" GROUP BY imageId
1287                            HAVING ".$val['valueHaving'];
1288            $returnedS.=") t".self::$tGlobalId." ";
1289          }
1290          else
1291          {
1292            $returnedS.="(".$val['value'].") t".self::$tGlobalId." ";
1293          }
1294
1295          if($tId>0) $returnedS.=" ON t".(self::$tGlobalId-1).".imageId = t".self::$tGlobalId.".imageId ";
1296          $tId++;
1297          self::$tGlobalId++;
1298        }
1299        $returnedS="SELECT DISTINCT '$requestNumber', t".(self::$tGlobalId-$tId).".imageId FROM ".$returnedS;
1300      }
1301      else
1302      {
1303        foreach($returned as $key=>$val)
1304        {
1305          if($returnedS!='') $returnedS.=" UNION DISTINCT ";
1306
1307          if($val['mode']=='item')
1308          {
1309            $returnedS.="SELECT DISTINCT '$requestNumber', t".self::$tGlobalId.".imageId
1310                          FROM (SELECT ".call_user_func(Array('RBCallBack'.$val['plugin'], 'getImageId'))." AS imageId
1311                                FROM ".call_user_func(Array('RBCallBack'.$val['plugin'], 'getFrom'));
1312            if($val['valueWhere']!='') $returnedS.=" WHERE ".$val['valueWhere'];
1313            if($val['valueHaving']!='')
1314              $returnedS.=" GROUP BY imageId
1315                            HAVING ".$val['valueHaving'];
1316            $returnedS.=") t".self::$tGlobalId." ";
1317          }
1318          else
1319          {
1320            $returnedS.="SELECT DISTINCT '$requestNumber', t".self::$tGlobalId.".imageId FROM (".$val['value'].") t".self::$tGlobalId;
1321          }
1322
1323          self::$tGlobalId++;
1324        }
1325      }
1326    }
1327
1328    return($returnedS);
1329  }
1330
1331
1332  /**
1333   * convert a list of images to HTML
1334   *
1335   * @param Array $imagesList : list of images id & associated datas
1336   * @return String : list formatted into HTML code
1337   */
1338  static protected function toHtml($imagesList)
1339  {
1340    global $template;
1341
1342    $template->set_filename('result_items',
1343                dirname(dirname(__FILE__)).'/templates/GPCRequestBuilder_result.tpl');
1344
1345
1346
1347    $template->assign('datas', $imagesList);
1348
1349    return($template->parse('result_items', true));
1350  }
1351
1352
1353  /**
1354   * returns allowed (or not allowed) categories for a user
1355   *
1356   * used the USER_CACHE_TABLE if possible
1357   *
1358   * @param Integer $userId : a valid user Id
1359   * @return String : IN(...), NOT IN(...) or nothing if there is no restriction
1360   *                  for the user
1361   */
1362  public function getUserCategories($userId)
1363  {
1364/*
1365    $returned='';
1366    if($user['forbidden_categories']!='')
1367    {
1368      $returned=Array(
1369        'JOIN' => 'AND ('.IMAGE_CATEGORY.'.category_id NOT IN ('.$user['forbidden_categories'].') ) ',
1370        'FROM' => IMAGE_CATEGORY
1371      );
1372
1373
1374    }
1375    *
1376    *
1377    */
1378  }
1379
1380
1381  /**
1382   * display search page
1383   *
1384   * @param Array $filter : an array of string ; each item is the name of a
1385   *                        registered plugin
1386   *                        if no parameters are given, no filter is applied
1387   *                        otherwise only plugin wich name is given are
1388   *                        accessible
1389   */
1390  static public function displaySearchPage($filter=array())
1391  {
1392    global $template, $lang;
1393
1394    if(is_string($filter)) $filter=array($filter);
1395    $filter=array_flip($filter);
1396
1397    GPCCore::addHeaderJS('jquery.ui', 'themes/default/js/ui/packed/ui.core.packed.js');
1398    GPCCore::addHeaderJS('jquery.ui.dialog', 'themes/default/js/ui/packed/ui.dialog.packed.js');
1399    GPCCore::addHeaderJS('gpc.pagesNavigator', 'plugins/GrumPluginClasses/js/pagesNavigator'.GPCCore::getMinified().'.js');
1400    GPCCore::addHeaderJS('gpc.rbSearch', 'plugins/GrumPluginClasses/js/rbSearch'.GPCCore::getMinified().'.js');
1401
1402
1403    $template->set_filename('gpc_search_page',
1404                dirname(dirname(__FILE__)).'/templates/GPCRequestBuilder_search.tpl');
1405
1406    $registeredPlugin=self::getRegistered();
1407    $dialogBox=Array();
1408    foreach($registeredPlugin as $key=>$val)
1409    {
1410      if(array_key_exists($key, $registeredPlugin) and
1411         (count($filter)==0 or array_key_exists($key, $filter)))
1412      {
1413        if(file_exists($registeredPlugin[$key]['fileName']))
1414        {
1415          include_once($registeredPlugin[$key]['fileName']);
1416
1417          $dialogBox[]=Array(
1418            'handle' => $val['name'].'DB',
1419            'dialogBoxClass' => call_user_func(Array('RBCallBack'.$key, 'getInterfaceDBClass')),
1420            'label' => call_user_func(Array('RBCallBack'.$key, 'getInterfaceLabel')),
1421            'content' => call_user_func(Array('RBCallBack'.$key, 'getInterfaceContent')),
1422          );
1423        }
1424      }
1425    }
1426
1427    $datas=Array(
1428      'dialogBox' => $dialogBox,
1429      'themeName' => defined('IN_ADMIN')?$template->get_themeconf('name'):'',
1430    );
1431
1432    $template->assign('datas', $datas);
1433
1434    return($template->parse('gpc_search_page', true));
1435  } //displaySearchPage
1436
1437}
1438
1439
1440?>
Note: See TracBrowser for help on using the repository browser.