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

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

release 3.4.3
bug:2167

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