source: extensions/AMetaData/amd_ajax.php @ 7447

Revision 7447, 56.3 KB checked in by grum, 9 years ago (diff)

implement feature bug:1924

Line 
1<?php
2/*
3 * -----------------------------------------------------------------------------
4 * Plugin Name: Advanced MetaData
5 * -----------------------------------------------------------------------------
6 * Author     : Grum
7 *   email    : grum@piwigo.org
8 *   website  : http://photos.grum.fr
9 *   PWG user : http://forum.piwigo.org/profile.php?id=3706
10 *
11 *   << May the Little SpaceFrog be with you ! >>
12 *
13 * -----------------------------------------------------------------------------
14 *
15 * See main.inc.php for release information
16 *
17 * manage all the ajax requests
18 * -----------------------------------------------------------------------------
19 */
20
21  define('PHPWG_ROOT_PATH',dirname(dirname(dirname(__FILE__))).'/');
22
23  /*
24   * set ajax module in admin mode if request is used for admin interface
25   */
26  if(!isset($_REQUEST['ajaxfct'])) $_REQUEST['ajaxfct']='';
27  if(preg_match('/^admin\./i', $_REQUEST['ajaxfct']))
28  {
29    define('IN_ADMIN', true);
30  }
31
32  // the common.inc.php file loads all the main.inc.php plugins files
33  include_once(PHPWG_ROOT_PATH.'include/common.inc.php' );
34  include_once(PHPWG_PLUGINS_PATH.'GrumPluginClasses/classes/GPCAjax.class.inc.php');
35  include_once('amd_root.class.inc.php');
36
37  load_language('plugin.lang', AMD_PATH);
38
39
40  class AMD_ajax extends AMD_root
41  {
42    private $tagSeparators=array(
43      'xmp.digiKam:TagsList' => '/',
44      'xmp.lr:hierarchicalSubject' => '|'
45    );
46
47    /**
48     * constructor
49     */
50    public function __construct($prefixeTable, $filelocation)
51    {
52      parent::__construct($prefixeTable, $filelocation);
53      $this->loadConfig();
54      $this->checkRequest();
55      $this->returnAjaxContent();
56    }
57
58    /**
59     * check the $_REQUEST values and set default values
60     *
61     */
62    protected function checkRequest()
63    {
64      global $user;
65
66      if(!isset($_REQUEST['ajaxfct'])) $_REQUEST['ajaxfct']='';
67
68      // check if asked function is valid
69      if(!(
70           $_REQUEST['ajaxfct']=='admin.makeStats.getList' or
71           $_REQUEST['ajaxfct']=='admin.makeStats.doAnalyze' or
72           $_REQUEST['ajaxfct']=='admin.makeStats.consolidate' or
73           $_REQUEST['ajaxfct']=='admin.showStats.getListTags' or
74           $_REQUEST['ajaxfct']=='admin.showStats.getListImages' or
75           $_REQUEST['ajaxfct']=='admin.updateTag.select' or
76           $_REQUEST['ajaxfct']=='admin.config.setOption' or
77           $_REQUEST['ajaxfct']=='admin.group.getList' or
78           $_REQUEST['ajaxfct']=='admin.group.delete' or
79           $_REQUEST['ajaxfct']=='admin.group.getNames' or
80           $_REQUEST['ajaxfct']=='admin.group.setNames' or
81           $_REQUEST['ajaxfct']=='admin.group.setOrder' or
82           $_REQUEST['ajaxfct']=='admin.group.getTagList' or
83           $_REQUEST['ajaxfct']=='admin.group.setTagList' or
84           $_REQUEST['ajaxfct']=='admin.group.getOrderedTagList' or
85           $_REQUEST['ajaxfct']=='admin.group.setOrderedTagList' or
86           $_REQUEST['ajaxfct']=='admin.userDefined.getList' or
87           $_REQUEST['ajaxfct']=='admin.userDefined.getTag' or
88           $_REQUEST['ajaxfct']=='admin.userDefined.setTag' or
89           $_REQUEST['ajaxfct']=='admin.userDefined.deleteTag' or
90           $_REQUEST['ajaxfct']=='admin.tag.getValues' or
91           $_REQUEST['ajaxfct']=='admin.tags.getKeywords' or
92           $_REQUEST['ajaxfct']=='admin.tags.convertKeywords' or
93
94           $_REQUEST['ajaxfct']=='public.makeStats.doPictureAnalyze')) $_REQUEST['ajaxfct']='';
95
96      if(preg_match('/^admin\./i', $_REQUEST['ajaxfct']) and !is_admin()) $_REQUEST['ajaxfct']='';
97
98      if($_REQUEST['ajaxfct']!='')
99      {
100        /*
101         * check admin.makeStats.getList values
102         */
103        if($_REQUEST['ajaxfct']=="admin.makeStats.getList")
104        {
105          if(!isset($_REQUEST['selectMode'])) $_REQUEST['selectMode']="caddieAdd";
106
107          if(!($_REQUEST['selectMode']=="notAnalyzed" or
108               $_REQUEST['selectMode']=="caddieAdd" or
109               $_REQUEST['selectMode']=="caddieReplace" or
110               $_REQUEST['selectMode']=="analyzed" or
111               $_REQUEST['selectMode']=="randomList" or
112               $_REQUEST['selectMode']=="all")) $_REQUEST['selectMode']="caddieAdd";
113
114          if($_REQUEST['selectMode']=="randomList" and
115              (!isset($_REQUEST['numOfRandomItems']) or
116               $_REQUEST['numOfRandomItems']<=0 or
117               preg_match('/^\d+$/', $_REQUEST['numOfRandomItems'])==0
118              )
119            ) $_REQUEST['ajaxfct']='';
120
121
122          if(!isset($_REQUEST['numOfItems'])) $_REQUEST['numOfItems']=25;
123
124          if(!isset($_REQUEST['ignoreOptions'])) $_REQUEST['ignoreOptions']=array();
125        }
126
127        /*
128         * check admin.makeStats.doAnalyze values
129         */
130        if($_REQUEST['ajaxfct']=="admin.makeStats.doAnalyze")
131        {
132          if(!isset($_REQUEST['imagesList'])) $_REQUEST['imagesList']="";
133        }
134
135        /*
136         * check admin.makeStats.consolidate values
137         */
138        if($_REQUEST['ajaxfct']=="admin.makeStats.consolidate")
139        {
140          if(!isset($_REQUEST['step'])) $_REQUEST['step']="*";
141        }
142
143        /*
144         * check admin.showStats.getListTags values
145         */
146        if($_REQUEST['ajaxfct']=="admin.showStats.getListTags")
147        {
148          if(!isset($_REQUEST['orderType'])) $_REQUEST['orderType']="tag";
149
150          if(!($_REQUEST['orderType']=="tag" or
151               $_REQUEST['orderType']=="label" or
152               $_REQUEST['orderType']=="num")) $_REQUEST['orderType']="tag";
153
154          if(!isset($_REQUEST['filterType'])) $_REQUEST['filterType']="";
155
156          if(!($_REQUEST['filterType']=="" or
157               ($_REQUEST['filterType']=="magic" and !in_array('magic', $this->config['amd_FillDataBaseExcludeFilters'])) or
158               $_REQUEST['filterType']=="userDefined" or
159               ($_REQUEST['filterType']=="exif" and !in_array('exif', $this->config['amd_FillDataBaseExcludeFilters'])) or
160               ($_REQUEST['filterType']=="exif.maker.Canon" and !in_array('maker', $this->config['amd_FillDataBaseExcludeFilters'])) or
161               ($_REQUEST['filterType']=="exif.maker.Nikon" and !in_array('maker', $this->config['amd_FillDataBaseExcludeFilters'])) or
162               ($_REQUEST['filterType']=="exif.maker.Pentax" and !in_array('maker', $this->config['amd_FillDataBaseExcludeFilters'])) or
163               ($_REQUEST['filterType']=="xmp" and !in_array('xmp', $this->config['amd_FillDataBaseExcludeFilters'])) or
164               ($_REQUEST['filterType']=="iptc"  and !in_array('iptc', $this->config['amd_FillDataBaseExcludeFilters']))
165               )) $_REQUEST['filterType']="";
166
167          if(!isset($_REQUEST['excludeUnusedTag'])) $_REQUEST['excludeUnusedTag']="n";
168
169          if(!($_REQUEST['excludeUnusedTag']=="y" or
170               $_REQUEST['excludeUnusedTag']=="n" )) $_REQUEST['excludeUnusedTag']="n";
171
172          if(!isset($_REQUEST['selectedTagOnly'])) $_REQUEST['selectedTagOnly']="n";
173
174          if(!($_REQUEST['selectedTagOnly']=="y" or
175               $_REQUEST['selectedTagOnly']=="n" )) $_REQUEST['selectedTagOnly']="n";
176        }
177
178        /*
179         * check admin.showStats.getListImages values
180         */
181        if($_REQUEST['ajaxfct']=="admin.showStats.getListImages")
182        {
183          if(!isset($_REQUEST['orderType'])) $_REQUEST['orderType']="num";
184
185          if(!($_REQUEST['orderType']=="value" or
186               $_REQUEST['orderType']=="num")) $_REQUEST['orderType']="num";
187
188          if(!isset($_REQUEST['tagId'])) $_REQUEST['tagId']="*";
189        }
190
191        /*
192         * check admin.updateTag.select values
193         */
194        if($_REQUEST['ajaxfct']=="admin.updateTag.select")
195        {
196          if(!isset($_REQUEST['numId'])) $_REQUEST['numId']="";
197
198          if(!isset($_REQUEST['tagSelected'])) $_REQUEST['tagSelected']="";
199        }
200
201        /*
202         * check admin.config.setOption values
203         */
204        if($_REQUEST['ajaxfct']=="admin.config.setOption")
205        {
206          if(!isset($_REQUEST['id'])) $_REQUEST['ajaxfct']='';
207          if(!isset($_REQUEST['value'])) $_REQUEST['ajaxfct']='';
208        }
209
210        /*
211         * check admin.group.delete values
212         */
213        if($_REQUEST['ajaxfct']=="admin.group.delete" and !isset($_REQUEST['id']))
214        {
215          $_REQUEST['id']="";
216        }
217
218        /*
219         * check admin.groupSetOrder values
220         */
221        if($_REQUEST['ajaxfct']=="admin.group.setOrder" and !isset($_REQUEST['listGroup']))
222        {
223          $_REQUEST['listGroup']="";
224        }
225
226        /*
227         * check admin.group.getNames values
228         */
229        if($_REQUEST['ajaxfct']=="admin.group.getNames" and !isset($_REQUEST['id']))
230        {
231          $_REQUEST['id']="";
232        }
233
234        /*
235         * check admin.group.setNames values
236         */
237        if($_REQUEST['ajaxfct']=="admin.group.setNames")
238        {
239          if(!isset($_REQUEST['listNames'])) $_REQUEST['listNames']="";
240
241          if(!isset($_REQUEST['id'])) $_REQUEST['id']="";
242        }
243
244        /*
245         * check admin.group.getTagList values
246         */
247        if($_REQUEST['ajaxfct']=="admin.group.getTagList" and !isset($_REQUEST['id']))
248        {
249          $_REQUEST['id']="";
250        }
251
252        /*
253         * check admin.group.setTagList values
254         */
255        if($_REQUEST['ajaxfct']=="admin.group.setTagList")
256        {
257          if(!isset($_REQUEST['id'])) $_REQUEST['id']="";
258
259          if(!isset($_REQUEST['listTag'])) $_REQUEST['listTag']="";
260        }
261
262        /*
263         * check admin.group.getOrderedTagList values
264         */
265        if($_REQUEST['ajaxfct']=="admin.group.getOrderedTagList" and !isset($_REQUEST['id']))
266        {
267          $_REQUEST['id']="";
268        }
269
270        /*
271         * check admin.group.setOrderedTagList values
272         */
273        if($_REQUEST['ajaxfct']=="admin.group.setOrderedTagList")
274        {
275          if(!isset($_REQUEST['id'])) $_REQUEST['id']="";
276
277          if(!isset($_REQUEST['listTag'])) $_REQUEST['listTag']="";
278        }
279
280        /*
281         * check admin.userDefined.getTag values
282         */
283        if($_REQUEST['ajaxfct']=="admin.userDefined.getTag" and !isset($_REQUEST['id']))
284        {
285          $_REQUEST['id']="";
286        }
287
288        /*
289         * check admin.userDefined.setTag values
290         */
291        if($_REQUEST['ajaxfct']=="admin.userDefined.setTag")
292        {
293          if(!isset($_REQUEST['id'])) $_REQUEST['id']="";
294          if($_REQUEST['id']!='' and !preg_match('/\d+/', $_REQUEST['id'])) $_REQUEST['id']="";
295
296          if(!isset($_REQUEST['properties']) or
297              (isset($_REQUEST['properties']) and
298               !(isset($_REQUEST['properties']['name']) and
299                 isset($_REQUEST['properties']['rules']) and
300                 isset($_REQUEST['properties']['tagId'])
301                )
302              )
303            ) $_REQUEST['ajaxfct']='';
304
305          if(isset($_REQUEST['properties']['rules']))
306          {
307            foreach($_REQUEST['properties']['rules'] as $val)
308            {
309              if(!(isset($val['order']) and
310                   isset($val['value']) and
311                   isset($val['parentId']) and
312                   isset($val['type']) and
313                   isset($val['defId']))) $_REQUEST['ajaxfct']='';
314            }
315          }
316        }
317
318        /*
319         * check admin.userDefined.deleteTag values
320         */
321        if($_REQUEST['ajaxfct']=="admin.userDefined.deleteTag" and !isset($_REQUEST['id']))
322        {
323          $_REQUEST['id']="";
324        }
325
326
327        /*
328         * check admin.tag.getValues values
329         */
330        if($_REQUEST['ajaxfct']=="admin.tag.getValues" and !isset($_REQUEST['id']))
331        {
332          $_REQUEST['ajaxfct']='';
333        }
334
335        /*
336         * check admin.tags.convertKeywords values
337         */
338        if($_REQUEST['ajaxfct']=="admin.tags.convertKeywords")
339        {
340          if(!isset($_REQUEST['keywords'])) $_REQUEST['keywords']=array();
341          if(!is_array($_REQUEST['keywords'])) $_REQUEST['keywords']=array();
342          if(count($_REQUEST['keywords'])==0) $_REQUEST['ajaxfct']='';
343        }
344
345
346
347
348
349        /*
350         * check public.makeStats.doPictureAnalyze values
351         */
352        if($_REQUEST['ajaxfct']=="public.makeStats.doPictureAnalyze")
353        {
354          if(!isset($_REQUEST['id'])) $_REQUEST['id']="0";
355        }
356      }
357    }
358
359
360    /**
361     * return ajax content
362     */
363    protected function returnAjaxContent()
364    {
365      $result="<p class='errors'>An error has occured</p>";
366      switch($_REQUEST['ajaxfct'])
367      {
368        case 'admin.makeStats.getList':
369          $result=$this->ajax_amd_admin_makeStatsGetList($_REQUEST['selectMode'], $_REQUEST['numOfItems'], $_REQUEST['ignoreOptions'], $_REQUEST['numOfRandomItems']);
370          break;
371        case 'admin.makeStats.doAnalyze':
372          $result=$this->ajax_amd_admin_makeStatsDoAnalyze($_REQUEST['imagesList']);
373          break;
374        case 'admin.makeStats.consolidate':
375          $result=$this->ajax_amd_admin_makeStatsConsolidate();
376          break;
377        case 'admin.showStats.getListTags':
378          $result=$this->ajax_amd_admin_showStatsGetListTags($_REQUEST['orderType'], $_REQUEST['filterType'], $_REQUEST['excludeUnusedTag'], $_REQUEST['selectedTagOnly']);
379          break;
380        case 'admin.showStats.getListImages':
381          $result=$this->ajax_amd_admin_showStatsGetListImages($_REQUEST['tagId'], $_REQUEST['orderType']);
382          break;
383        case 'admin.updateTag.select':
384          $result=$this->ajax_amd_admin_updateTagSelect($_REQUEST['numId'], $_REQUEST['tagSelected']);
385          break;
386        case 'admin.config.setOption':
387          $result=$this->ajax_amd_admin_configSetOption($_REQUEST['id'], $_REQUEST['value']);
388          break;
389        case 'admin.group.getList':
390          $result=$this->ajax_amd_admin_groupGetList();
391          break;
392        case 'admin.group.delete':
393          $result=$this->ajax_amd_admin_groupDelete($_REQUEST['id']);
394          break;
395        case 'admin.group.getNames':
396          $result=$this->ajax_amd_admin_groupGetNames($_REQUEST['id']);
397          break;
398        case 'admin.group.setNames':
399          $result=$this->ajax_amd_admin_groupSetNames($_REQUEST['id'], $_REQUEST['listNames']);
400          break;
401        case 'admin.group.setOrder':
402          $result=$this->ajax_amd_admin_groupSetOrder($_REQUEST['listGroup']);
403          break;
404        case 'admin.group.getTagList':
405          $result=$this->ajax_amd_admin_groupGetTagList($_REQUEST['id']);
406          break;
407        case 'admin.group.setTagList':
408          $result=$this->ajax_amd_admin_groupSetTagList($_REQUEST['id'], $_REQUEST['listTag']);
409          break;
410        case 'admin.group.getOrderedTagList':
411          $result=$this->ajax_amd_admin_groupGetOrderedTagList($_REQUEST['id']);
412          break;
413        case 'admin.group.setOrderedTagList':
414          $result=$this->ajax_amd_admin_groupSetOrderedTagList($_REQUEST['id'], $_REQUEST['listTag']);
415          break;
416        case 'admin.userDefined.getList':
417          $result=$this->ajax_amd_admin_userDefinedGetList();
418          break;
419        case 'admin.userDefined.getTag':
420          $result=$this->ajax_amd_admin_userDefinedGetTag($_REQUEST['id']);
421          break;
422        case 'admin.userDefined.setTag':
423          $result=$this->ajax_amd_admin_userDefinedSetTag($_REQUEST['id'], $_REQUEST['properties']);
424          break;
425        case 'admin.userDefined.deleteTag':
426          $result=$this->ajax_amd_admin_userDefinedDeleteTag($_REQUEST['id']);
427          break;
428        case 'admin.tag.getValues':
429          $result=$this->ajax_amd_admin_tagGetValues($_REQUEST['id']);
430          break;
431        case 'admin.tags.getKeywords':
432          $result=$this->ajax_amd_admin_tagsGetKeywords();
433          break;
434        case 'admin.tags.convertKeywords':
435          $result=$this->ajax_amd_admin_tagsConvertKeywords($_REQUEST['keywords']);
436          break;
437
438
439        case 'public.makeStats.doPictureAnalyze':
440          $result=$this->ajax_amd_public_makeStatsDoPictureAnalyze($_REQUEST['id']);
441          break;
442      }
443      GPCAjax::returnResult($result);
444    }
445
446    /*------------------------------------------------------------------------*
447     *
448     * PUBLIC FUNCTIONS
449     *
450     *----------------------------------------------------------------------- */
451    private function ajax_amd_public_makeStatsDoPictureAnalyze($imageId)
452    {
453      if($imageId==0)
454      {
455        // get a randomly picture...
456        $sql="SELECT pai.imageId, pi.path, pi.has_high
457              FROM ".$this->tables['images']." pai
458                LEFT JOIN ".IMAGES_TABLE." pi ON pai.imageId=pi.id
459              WHERE analyzed='n'
460              ORDER BY RAND() LIMIT 1;";
461      }
462      else
463      {
464        $sql="SELECT path, id AS imageId
465              FROM ".IMAGES_TABLE."
466              WHERE id='$imageId';";
467      }
468
469      $result=pwg_query($sql);
470      if($result)
471      {
472        $path=dirname(dirname(dirname(__FILE__)));
473        while($row=pwg_db_fetch_assoc($result))
474        {
475          $imageId=$row['imageId'];
476          if($row['has_high']==='true' and $this->config['amd_UseMetaFromHD']=='y')
477          {
478            $filename=$path."/".dirname($row['path'])."/pwg_high/".basename($row['path']);
479          }
480          else
481          {
482            $filename=$path."/".$row['path'];
483          }
484        }
485
486        $this->analyzeImageFile($filename, $imageId);
487        $this->makeStatsConsolidation();
488
489        return("Analyze of image #$imageId is a success !");
490      }
491
492      return("Try to analyze image #$imageId failed...");
493
494    }
495
496
497
498    /*------------------------------------------------------------------------*
499     *
500     * ADMIN FUNCTIONS
501     *
502     *----------------------------------------------------------------------- */
503
504    /**
505     * return a list of picture Id
506     *
507     * picture id are separated with a space " "
508     * picture id are grouped in blocks of 'amd_NumberOfItemsPerRequest' items and
509     * are separated with a semi-colon ";"
510     *
511     * client side just have to split blocks, and transmit it to the server
512     *
513     * There is two mode to determine the pictures being analyzed :
514     *  - "all"         : analyze all the images
515     *  - "notAnalyzed" : analyze only the images not yet analyzed
516     *
517     * @param String $mode
518     * @param Integer $nbOfItems : number of items per request
519     * @param
520     * @param Integer $numOfRandomItems : number of random items (used if $mode=='randomList')
521     * @return String : list of image id to be analyzed, separated with a space
522     *                      "23 78 4523 5670"
523     */
524    private function ajax_amd_admin_makeStatsGetList($mode, $nbOfItems, $ignoreSchemas, $numOfRandomItems)
525    {
526      global $user;
527
528      $returned="";
529      $this->config['amd_FillDataBaseIgnoreSchemas']=$ignoreSchemas;
530      $this->config['amd_NumberOfItemsPerRequest']=$nbOfItems;
531      $this->saveConfig();
532
533      $sql="SELECT ait.imageId FROM ".$this->tables['images']." ait";
534      if($mode=='notAnalyzed' or $mode=='randomList' )
535      {
536        $sql.=" WHERE ait.analyzed='n'";
537      }
538      elseif($mode=='caddieAdd' or $mode=='caddieReplace')
539      {
540        $sql.=" LEFT JOIN ".CADDIE_TABLE." ct ON ait.imageId = ct.element_id
541              WHERE ct.user_id = ".$user['id']." ";
542
543        if($mode=='caddieAdd') $sql.=" AND ait.analyzed='n'";
544      }
545      elseif($mode=='analyzed')
546      {
547        $sql.=" WHERE ait.analyzed='y'";
548
549        pwg_query("UPDATE ".$this->tables['images']." SET nbTags=0 WHERE analyzed='y';");
550        pwg_query("UPDATE ".$this->tables['used_tags']." SET numOfImg=0");
551        pwg_query("DELETE FROM ".$this->tables['images_tags']);
552      }
553
554      if($mode=='all' or $mode=='caddieReplace')
555      {
556        pwg_query("UPDATE ".$this->tables['images']." SET analyzed='n', nbTags=0");
557        pwg_query("UPDATE ".$this->tables['used_tags']." SET numOfImg=0");
558        pwg_query("DELETE FROM ".$this->tables['images_tags']);
559      }
560
561      if($mode=='randomList')
562      {
563        $sql.=" ORDER BY RAND() LIMIT 0, $numOfRandomItems;";
564      }
565
566      $result=pwg_query($sql);
567      if($result)
568      {
569        $i=0;
570        while($row=pwg_db_fetch_row($result))
571        {
572          $returned.=$row[0];
573          $i++;
574          if($i>=$nbOfItems)
575          {
576            $returned.=";";
577            $i=0;
578          }
579          else
580          {
581            $returned.=" ";
582          }
583        }
584      }
585      return(trim($returned).";");
586    }
587
588
589    /**
590     * extract metadata from images
591     *
592     * @param String $imageList : list of image id to be analyzed, separated with
593     *                            a space
594     *                                "23 78 4523 5670"
595     * @return String : list of the analyzed pictures, with number of tags found
596     *                  for each picture
597     *                    "23=0;78=66;4523=33;5670=91;"
598     */
599    private function ajax_amd_admin_makeStatsDoAnalyze($imagesList)
600    {
601      $list=explode(" ", trim($imagesList));
602
603      $returned="";
604
605      if(count($list)>0 and trim($imagesList)!='')
606      {
607        // $path = path of piwigo's on the server filesystem
608        $path=dirname(dirname(dirname(__FILE__)));
609
610        $sql="SELECT id, path, has_high FROM ".IMAGES_TABLE." WHERE id IN (".implode(", ", $list).")";
611        $result=pwg_query($sql);
612        if($result)
613        {
614          while($row=pwg_db_fetch_assoc($result))
615          {
616            /*
617             * in some case (in a combination of some pictures), when there is too
618             * much pictures to analyze in the same request, a fatal error occurs
619             * with the message : "Allowed memory size of XXXXX bytes exhausted"
620             *
621             *
622             * tracking memory leak is not easy... :-(
623             *
624             */
625            //echo "analyzing:".$row['id']."\n";
626            //$mem1=memory_get_usage();
627            //echo "memory before analyze:".$mem1."\n";
628            if($row['has_high']==='true' and $this->config['amd_UseMetaFromHD']=='y')
629            {
630              $returned.=$this->analyzeImageFile($path."/".dirname($row['path'])."/pwg_high/".basename($row['path']), $row['id']);
631            }
632            else
633            {
634              $returned.=$this->analyzeImageFile($path."/".$row['path'], $row['id']);
635            }
636            //echo $returned."\n";
637            //$mem2=memory_get_usage();
638            //echo "memory after analyze:".$mem2." (".($mem2-$mem1).")\n";
639          }
640        }
641      }
642      return($returned);
643    }
644
645    /**
646     * do some consolidation on database to optimize other requests
647     *
648     */
649    private function ajax_amd_admin_makeStatsConsolidate()
650    {
651      $this->makeStatsConsolidation();
652    }
653
654    /**
655     * return a formatted <table> (using the template "amd_stat_show_iListTags")
656     * of used tag with, for each tag, the number and the percentage of pictures
657     * where the tag was found
658     *
659     * @param String $orderType : order for the list (by tag 'tag' or by number of
660     *                            pictures 'num')
661     * @param String $filterType : filter for the list ('exif', 'xmp', 'iptc' or '')
662     * @return String
663     */
664    private function ajax_amd_admin_showStatsGetListTags($orderType, $filterType, $excludeUnusedTag, $selectedTagOnly)
665    {
666      global $template;
667
668      $this->config['amd_GetListTags_OrderType'] = $orderType;
669      $this->config['amd_GetListTags_FilterType'] = $filterType;
670      $this->config['amd_GetListTags_ExcludeUnusedTag'] = $excludeUnusedTag;
671      $this->config['amd_GetListTags_SelectedTagOnly'] = $selectedTagOnly;
672      $this->saveConfig();
673
674      $local_tpl = new Template(AMD_PATH."admin/", "");
675      $local_tpl->set_filename('body_page',
676                    dirname($this->getFileLocation()).'/admin/amd_metadata_select_iListTags.tpl');
677
678      $numOfPictures=$this->getNumOfPictures();
679
680      $datas=array();
681      $sql="SELECT ut.numId, ut.tagId, ut.translatable, ut.name, ut.numOfImg, if(st.tagId IS NULL, 'n', 'y') as checked, ut.translatedName
682              FROM ".$this->tables['used_tags']." ut
683                LEFT JOIN ".$this->tables['selected_tags']." st
684                  ON st.tagId = ut.tagId ";
685      $where="";
686
687      if($filterType!='')
688      {
689        if($filterType=='exif')
690        {
691          $where.=" WHERE ut.tagId LIKE 'exif.tiff.%'
692                      OR ut.tagId LIKE 'exif.exif.%'
693                      OR ut.tagId LIKE 'exif.gps.%'  ";
694        }
695        else
696        {
697          $where.=" WHERE ut.tagId LIKE '".$filterType.".%' ";
698        }
699      }
700
701      if($excludeUnusedTag=='y')
702      {
703        ($where=="")?$where=" WHERE ":$where.=" AND ";
704        $where.=" ut.numOfImg > 0 ";
705      }
706
707      if($selectedTagOnly=='y')
708      {
709        ($where=="")?$where=" WHERE ":$where.=" AND ";
710        $where.=" st.tagId IS NOT NULL ";
711      }
712
713      $sql.=$where;
714
715      switch($orderType)
716      {
717        case 'tag':
718          $sql.=" ORDER BY tagId ASC";
719          break;
720        case 'num':
721          $sql.=" ORDER BY numOfImg DESC, tagId ASC";
722          break;
723        case 'label':
724          $sql.=" ORDER BY translatedName ASC, tagId ASC";
725          break;
726      }
727
728      $result=pwg_query($sql);
729      if($result)
730      {
731        while($row=pwg_db_fetch_assoc($result))
732        {
733          $datas[]=array(
734            "numId" => $row['numId'],
735            "tagId" => $row['tagId'],
736            "label" => L10n::get($row['name']),
737            "nb"    => $row['numOfImg'],
738            "pct"   => ($numOfPictures!=0)?sprintf("%.2f", 100*$row['numOfImg']/$numOfPictures):"0",
739            "tagChecked" => ($row['checked']=='y')?"checked":""
740          );
741        }
742      }
743
744      $local_tpl->assign('themeconf', Array('name' => $template->get_themeconf('name')));
745      $local_tpl->assign('datas', $datas);
746
747      return($local_tpl->parse('body_page', true));
748    }
749
750
751    /*
752     *
753     *
754     */
755    private function ajax_amd_admin_showStatsGetListImages($tagId, $orderType)
756    {
757      global $template;
758
759      $this->config['amd_GetListImages_OrderType'] = $orderType;
760      $this->saveConfig();
761
762      $local_tpl = new Template(AMD_PATH."admin/", "");
763      $local_tpl->set_filename('body_page',
764                    dirname($this->getFileLocation()).'/admin/amd_metadata_select_iListImages.tpl');
765
766
767
768      $datas=array();
769      $sql="SELECT ut.translatable, ut.numOfImg, COUNT(it.imageId) AS Nb, it.value
770              FROM ".$this->tables['used_tags']." ut
771                LEFT JOIN ".$this->tables['images_tags']." it
772                ON ut.numId = it.numId
773              WHERE ut.tagId = '".$tagId."'
774                AND it.value IS NOT NULL
775              GROUP BY it.value
776              ORDER BY ";
777      switch($orderType)
778      {
779        case 'value':
780          $sql.="it.value ASC";
781          break;
782        case 'num':
783          $sql.="Nb DESC";
784          break;
785      }
786
787      $result=pwg_query($sql);
788      if($result)
789      {
790        while($row=pwg_db_fetch_assoc($result))
791        {
792          $datas[]=array(
793            "value" => AMD_root::prepareValueForDisplay($row['value'], ($row['translatable']=='y'), ", "),
794            "nb"    => $row['Nb'],
795            "pct"   => ($row['numOfImg']!=0)?sprintf("%.2f", 100*$row['Nb']/$row['numOfImg']):"-"
796          );
797        }
798      }
799
800      if(count($datas)>0)
801      {
802        $local_tpl->assign('themeconf', Array('name' => $template->get_themeconf('name')));
803        $local_tpl->assign('datas', $datas);
804        return($local_tpl->parse('body_page', true));
805      }
806      else
807      {
808        return("<div style='width:100%;text-align:center;padding-top:20px;'>".l10n('g003_selected_tag_isnot_linked_with_any_picture')."</div>");
809      }
810    }
811
812
813    /*
814     *
815     *
816     */
817    private function ajax_amd_admin_updateTagSelect($numId, $selected)
818    {
819      if($selected=='y')
820      {
821        $sql="SELECT ut.tagId FROM ".$this->tables['selected_tags']." st
822                LEFT JOIN ".$this->tables['used_tags']." ut
823                  ON ut.tagID = st.tagId
824                WHERE ut.numId = $numId;";
825        $result=pwg_query($sql);
826        if($result)
827        {
828          if(pwg_db_num_rows($result)==0)
829          {
830            $sql="INSERT INTO ".$this->tables['selected_tags']."
831                    SELECT ut.tagId, 0, -1
832                    FROM ".$this->tables['used_tags']." ut
833                      LEFT JOIN ".$this->tables['selected_tags']." st
834                        ON ut.tagID = st.tagId
835                    WHERE ut.numId = $numId;";
836            pwg_query($sql);
837          }
838        }
839      }
840      elseif($selected=='n')
841      {
842        $sql="DELETE FROM ".$this->tables['selected_tags']." st
843                USING ".$this->tables['used_tags']." ut
844                  LEFT JOIN ".$this->tables['selected_tags']." st
845                    ON ut.tagID = st.tagId
846                WHERE ut.numId = $numId;";
847        pwg_query($sql);
848      }
849
850    }
851
852
853    /**
854     * this function return the list of tags :
855     *  - associated with the group
856     *  - not associated with a group
857     * the list is used to make tags selection
858     *
859     * @param String $id      : Id of the current group
860     * @return String : an HTML formatted list with checkbox
861     */
862    private function ajax_amd_admin_groupGetTagList($id)
863    {
864      global $template;
865
866      if($id!="")
867      {
868        $sql="SELECT st.tagId, st.groupId, ut.name, ut.numId
869              FROM ".$this->tables['selected_tags']." st
870                LEFT JOIN ".$this->tables['used_tags']." ut
871                  ON st.tagId = ut.tagId
872              ORDER BY tagId";
873        $result=pwg_query($sql);
874        if($result)
875        {
876          $datas=Array();
877          while($row=pwg_db_fetch_assoc($result))
878          {
879            if($row['groupId']==$id)
880            {
881              $state="checked";
882            }
883            elseif($row['groupId']==-1)
884            {
885              $state="";
886            }
887            else
888            {
889              $state="n/a";
890            }
891
892            if($state!="n/a")
893              $datas[]=Array(
894                'tagId' => $row['tagId'],
895                'name'  => L10n::get($row['name']),
896                'state' => $state,
897                'numId' => $row['numId']
898              );
899          }
900
901          if(count($datas)>0)
902          {
903            $local_tpl = new Template(AMD_PATH."admin/", "");
904            $local_tpl->set_filename('body_page',
905                          dirname($this->getFileLocation()).'/admin/amd_metadata_display_groupListTagSelect.tpl');
906            $local_tpl->assign('themeconf', Array('name' => $template->get_themeconf('name')));
907            $local_tpl->assign('datas', $datas);
908            return($local_tpl->parse('body_page', true));
909          }
910          else
911          {
912            return(l10n("g003_no_tag_can_be_selected"));
913          }
914        }
915      }
916      else
917      {
918        return(l10n("g003_invalid_group_id"));
919      }
920    }
921
922
923    /**
924     * this function associate tags to a group
925     *
926     * @param String $id      : Id of group
927     * @param String $listTag : list of selected tags, items are separated by a
928     *                          semi-colon ";" char
929     */
930    private function ajax_amd_admin_groupSetTagList($id, $listTag)
931    {
932      if($id!="")
933      {
934        $sql="UPDATE ".$this->tables['selected_tags']."
935              SET groupId = -1
936              WHERE groupId = $id;";
937        pwg_query($sql);
938
939        if($listTag!="")
940        {
941          $sql="UPDATE ".$this->tables['selected_tags']." st, ".$this->tables['used_tags']." ut
942                SET st.groupId = $id
943                WHERE st.tagId = ut.tagId
944                  AND ut.numId IN ($listTag);";
945          pwg_query($sql);
946        }
947      }
948      else
949      {
950        return("KO");
951      }
952    }
953
954
955    /**
956     * this function returns an ordered list of tags associated with a group
957     *
958     * @param String $id        : the group Id
959     * @return String : an HTML formatted list
960     */
961    private function ajax_amd_admin_groupGetOrderedTagList($id)
962    {
963      global $template;
964      if($id!="")
965      {
966        $numOfPictures=$this->getNumOfPictures();
967
968        $sql="SELECT st.tagId, ut.name, ut.numId, ut.numOfImg
969              FROM ".$this->tables['selected_tags']." st
970                LEFT JOIN ".$this->tables['used_tags']." ut
971                  ON st.tagId = ut.tagId
972              WHERE st.groupId = $id
973              ORDER BY st.order ASC, st.tagId ASC";
974        $result=pwg_query($sql);
975        if($result)
976        {
977          $datas=Array();
978          while($row=pwg_db_fetch_assoc($result))
979          {
980            $datas[]=Array(
981              'tagId' => $row['tagId'],
982              'name'  => L10n::get($row['name']),
983              'numId' => $row['numId'],
984              'nbItems' => ($this->config['amd_InterfaceMode']=='advanced')?$row['numOfImg']:'',
985              'pct'   => ($this->config['amd_InterfaceMode']=='advanced')?(($numOfPictures==0)?"0":sprintf("%.2f", 100*$row['numOfImg']/$numOfPictures)):''
986            );
987          }
988
989          if(count($datas)>0)
990          {
991            $template->set_filename('list_page',
992                          dirname($this->getFileLocation()).'/admin/amd_metadata_display_groupListTagOrder.tpl');
993            $template->assign('datas', $datas);
994            $template->assign('group', $id);
995            return($template->parse('list_page', true));
996          }
997          else
998          {
999            return(l10n("g003_no_tag_can_be_selected"));
1000          }
1001        }
1002      }
1003      else
1004      {
1005        return(l10n("g003_invalid_group_id"));
1006      }
1007    }
1008
1009
1010    /**
1011     * this function update the tags order inside a group
1012     *
1013     * @param String $id        : the group Id
1014     * @param String $listGroup : the ordered list of tags, items are separated
1015     *                            by a semi-colon ";" char
1016     */
1017    private function ajax_amd_admin_groupSetOrderedTagList($id, $listTag)
1018    {
1019      $tags=explode(';', $listTag);
1020      if($id!="" and count($tags)>0)
1021      {
1022        /*
1023         * by default, all items are set with order equals -1 (if list is not
1024         * complete, forgotten items are sorted in head)
1025         */
1026        pwg_query("UPDATE ".$this->tables['selected_tags']." st
1027                    SET st.order = -1
1028                    WHERE st.groupId = $id;");
1029
1030        foreach($tags as $key=>$val)
1031        {
1032          $sql="UPDATE ".$this->tables['selected_tags']." st, ".$this->tables['used_tags']." ut
1033                SET st.order = $key
1034                WHERE st.groupId = $id
1035                  AND st.tagId = ut.tagId
1036                  AND ut.numId = $val;";
1037          $result=pwg_query($sql);
1038        }
1039      }
1040    }
1041
1042
1043
1044    /**
1045     * this function update the groups order
1046     *
1047     * @param String $listGroup : the ordered list of groups, items are separated
1048     *                            by a semi-colon ";" char
1049     */
1050    private function ajax_amd_admin_groupSetOrder($listGroup)
1051    {
1052      $groups=explode(";",$listGroup);
1053      if(count($groups)>0)
1054      {
1055        /*
1056         * by default, all items are set with order equals -1 (if list is not
1057         * complete, forgotten items are sorted in head)
1058         */
1059        pwg_query("UPDATE ".$this->tables['groups']." g SET g.order = -1;");
1060
1061        foreach($groups as $key=>$val)
1062        {
1063          $sql="UPDATE ".$this->tables['groups']." g
1064                SET g.order = $key
1065                WHERE g.groupId = $val;";
1066          $result=pwg_query($sql);
1067        }
1068      }
1069    }
1070
1071    /**
1072     * this function is used to create a new group ($groupId = "") or update the
1073     * group name (names are given in all langs in a list)
1074     *
1075     * @param String $groupId : the groupId to update, or "" to create a new groupId
1076     * @param String $listNames : name of the group, in all language given as a
1077     *                            list ; each lang is separated by a carraige
1078     *                            return "\n" char, each items is defined as
1079     *                            lang=value
1080     *                              en_UK=the name group
1081     *                              fr_FR=le nom du groupe
1082     */
1083    private function ajax_amd_admin_groupSetNames($groupId, $listNames)
1084    {
1085      $names=explode("\n", $listNames);
1086      if($groupId=="" and count($names)>0)
1087      {
1088        $sql="INSERT INTO ".$this->tables['groups']." VALUES('', 9999)";
1089        $result=pwg_query($sql);
1090        $groupId=pwg_db_insert_id();
1091      }
1092
1093      if(is_numeric($groupId) and count($names)>0)
1094      {
1095        $sql="DELETE FROM ".$this->tables['groups_names']."
1096              WHERE groupId = $groupId;";
1097        pwg_query($sql);
1098
1099
1100        $sql="";
1101        foreach($names as $val)
1102        {
1103          $tmp=explode("=", $val);
1104          if($sql!="") $sql.=", ";
1105          $sql.=" ($groupId, '".$tmp[0]."', '".$tmp[1]."')";
1106        }
1107        $sql="INSERT INTO ".$this->tables['groups_names']." VALUES ".$sql;
1108        pwg_query($sql);
1109      }
1110    }
1111
1112    /**
1113     * this function returns an html form, allowing to manage the group
1114     *
1115     * @param String $groupId : the groupId to manage, or "" to return a creation
1116     *                          form
1117     * @return String : the form
1118     */
1119    private function ajax_amd_admin_groupGetNames($groupId)
1120    {
1121      global $user;
1122
1123      $local_tpl = new Template(AMD_PATH."admin/", "");
1124      $local_tpl->set_filename('body_page',
1125                    dirname($this->getFileLocation()).'/admin/amd_metadata_display_groupEdit.tpl');
1126
1127      $datasLang=array(
1128        'language_list' => Array(),
1129        'lang_selected' => $user['language'],
1130        'fromlang' => substr($user['language'],0,2),
1131        'default' => ''
1132      );
1133
1134      $langs=get_languages();
1135      foreach($langs as $key => $val)
1136      {
1137        $datasLang['language_list'][$key] = Array(
1138          'langName' => str_replace("\n", "", $val),
1139          'name' => ""
1140        );
1141      }
1142
1143      if($groupId!="")
1144      {
1145        $sql="SELECT lang, name FROM ".$this->tables['groups_names']."
1146              WHERE groupId = $groupId;";
1147        $result=pwg_query($sql);
1148        if($result)
1149        {
1150          while($row=pwg_db_fetch_assoc($result))
1151          {
1152            if(array_key_exists($row['lang'], $datasLang['language_list']))
1153            {
1154              $datasLang['language_list'][$row['lang']]['name']=htmlentities($row['name'], ENT_QUOTES, 'UTF-8');
1155              if($user['language']==$row['lang'])
1156              {
1157                $datasLang['default']=$datasLang['language_list'][$row['lang']]['name'];
1158              }
1159            }
1160          }
1161        }
1162      }
1163
1164      $local_tpl->assign('datasLang', $datasLang);
1165
1166      return($local_tpl->parse('body_page', true));
1167    }
1168
1169
1170    /**
1171     * this function returns an html form, allowing to manage the group
1172     *
1173     * @param String $groupId : the groupId to manage, or "" to return a creation
1174     *                          form
1175     * @return String : the form
1176     */
1177    private function ajax_amd_admin_groupGetList()
1178    {
1179      global $user, $template;
1180
1181      //$local_tpl = new Template(AMD_PATH."admin/", "");
1182      $template->set_filename('group_list',
1183                    dirname($this->getFileLocation()).'/admin/amd_metadata_display_groupList.tpl');
1184
1185
1186      $datas=array(
1187        'groups' => Array(),
1188      );
1189
1190      $sql="SELECT g.groupId, gn.name
1191            FROM ".$this->tables['groups']." g
1192              LEFT JOIN ".$this->tables['groups_names']." gn
1193                ON g.groupId = gn.groupId
1194            WHERE gn.lang = '".$user['language']."'
1195            ORDER BY g.order;";
1196      $result=pwg_query($sql);
1197      if($result)
1198      {
1199        while($row=pwg_db_fetch_assoc($result))
1200        {
1201          $datas['groups'][]=Array(
1202            'id' => $row['groupId'],
1203            'name' => htmlentities($row['name'], ENT_QUOTES, "UTF-8")
1204          );
1205        }
1206      }
1207
1208      $template->assign('datas', $datas);
1209      return($template->parse('group_list', true));
1210    }
1211
1212
1213    /**
1214     * delete the group
1215     * associated tag returns in the available tag list
1216     *
1217     * @param String $groupId : the groupId to delete
1218     */
1219    private function ajax_amd_admin_groupDelete($groupId)
1220    {
1221      if($groupId!="")
1222      {
1223        $sql="DELETE FROM ".$this->tables['groups']."
1224              WHERE groupId = $groupId;";
1225        pwg_query($sql);
1226
1227        $sql="DELETE FROM ".$this->tables['groups_names']."
1228              WHERE groupId = $groupId;";
1229        pwg_query($sql);
1230
1231        $sql="UPDATE ".$this->tables['selected_tags']."
1232              SET groupId = -1
1233              WHERE groupId = $groupId;";
1234        pwg_query($sql);
1235      }
1236    }
1237
1238
1239    /**
1240     * return the list of userDefined tag
1241     *
1242     * @return String : an HTML list ready to use
1243     */
1244    private function ajax_amd_admin_userDefinedGetList()
1245    {
1246      global $user, $template;
1247
1248      //$local_tpl = new Template(AMD_PATH."admin/", "");
1249      $template->set_filename('userDefList',
1250                    dirname($this->getFileLocation()).'/admin/amd_metadata_personnal_iListTags.tpl');
1251
1252      $datas=array();
1253
1254      $sql="SELECT aut.numId, aut.tagId, aut.translatedName, COUNT(autd.defId) AS numOfRules
1255            FROM ".$this->tables['used_tags']." aut
1256              LEFT JOIN ".$this->tables['user_tags_def']." autd ON aut.numId=autd.numId
1257            WHERE aut.tagId LIKE 'userDefined.%'
1258            GROUP BY aut.numId
1259            ORDER BY aut.tagId;";
1260      $result=pwg_query($sql);
1261      if($result)
1262      {
1263        while($row=pwg_db_fetch_assoc($result))
1264        {
1265          $datas[]=Array(
1266            'numId' => $row['numId'],
1267            'tagId' => $row['tagId'],
1268            'label' => htmlspecialchars($row['translatedName'], ENT_QUOTES, "UTF-8"),
1269            'numOfRules' => $row['numOfRules']
1270          );
1271        }
1272      }
1273
1274      $template->assign('datas', $datas);
1275      return($template->parse('userDefList', true));
1276    }
1277
1278    /**
1279     * returns a userDefined tag
1280     *
1281     * @param String $id :
1282     * @return String :
1283     */
1284    private function ajax_amd_admin_userDefinedGetTag($id)
1285    {
1286      $returned=array(
1287        'numId' => 0,
1288        'tagId' => '',
1289        'label' => '',
1290        'rules' => Array(),
1291        'lastDefId' => 1,
1292      );
1293
1294      $sql="SELECT aut.numId, aut.tagId, aut.name, MAX(autd.defId) AS lastDefId
1295            FROM ".$this->tables['used_tags']." aut
1296              LEFT JOIN ".$this->tables['user_tags_def']." autd ON autd.numId=aut.numId
1297            WHERE aut.numId='$id'
1298            GROUP BY aut.numId";
1299      $result=pwg_query($sql);
1300      if($result)
1301      {
1302        while($row=pwg_db_fetch_assoc($result))
1303        {
1304          $returned['numId']=$row['numId'];
1305          $returned['tagId']=$row['tagId'];
1306          $returned['label']=$row['name'];
1307          $returned['lastDefId']=$row['lastDefId'];
1308        }
1309
1310        $sql="SELECT numId, defId, parentId, `order`, type, value, conditionType, conditionValue
1311              FROM ".$this->tables['user_tags_def']."
1312              WHERE numId='$id'
1313              ORDER BY numId, `order`";
1314        $result=pwg_query($sql);
1315        if($result)
1316        {
1317          while($row=pwg_db_fetch_assoc($result))
1318          {
1319            $returned['rules'][]=$row;
1320          }
1321        }
1322      }
1323
1324      return(json_encode($returned));
1325    }
1326
1327
1328    /**
1329     * set a userDefined tag
1330     *
1331     * @param String $id :
1332     * @param Array $properties :
1333     * @return String : ok or ko
1334     */
1335    private function ajax_amd_admin_userDefinedSetTag($id, $properties)
1336    {
1337      global $user;
1338
1339      $currentTagId='';
1340
1341      if(!preg_match('/^userDefined\./', $properties['tagId']))
1342      {
1343        $properties['tagId']='userDefined.'.$properties['tagId'];
1344      }
1345
1346      $sql="SELECT numId, tagId FROM ".$this->tables['used_tags']."
1347            WHERE tagId='".$properties['tagId']."';";
1348      $result=pwg_query($sql);
1349      if($result)
1350      {
1351        while($row=pwg_db_fetch_assoc($result))
1352        {
1353          if($row['numId']!=$id)
1354          {
1355            return('iBDTagId!'.l10n('g003_tagIdAlreadyExist'));
1356          }
1357          $currentTagId=$row['tagId'];
1358        }
1359      }
1360
1361      /*
1362       * to set a user defined tag
1363       *  1/ if it's a new user tag, create the tag into the used_tags table to
1364       *     get a new numId for the tag
1365       *  2/ delete all properties into the user_tags_def
1366       *  3/ insert the properties
1367       */
1368      if($id=='')
1369      {
1370        // add a new metadata
1371        $sql="INSERT INTO ".$this->tables['used_tags']."
1372              VALUES ('', '".$properties['tagId']."', 'n', '".$properties['name']."', 0, '".$properties['name']."')";
1373        $result=pwg_query($sql);
1374        $id=pwg_db_insert_id();
1375
1376        /*
1377         * multilanguage management will be coded later....
1378        $sql="INSERT INTO ".$this->tables['user_tags_label']."
1379              VALUES ('$id', '".$user['language']."', '".$properties['name']."');";
1380        $result=pwg_query($sql);
1381        */
1382
1383        if($this->config['amd_InterfaceMode']=='basic')
1384        {
1385          $sql="INSERT INTO ".$this->tables['selected_tags']." VALUES ('".$properties['tagId']."', 0, -1);";
1386          pwg_query($sql);
1387        }
1388      }
1389      else
1390      {
1391        //update an existing metadata
1392        $sql="UPDATE ".$this->tables['used_tags']."
1393              SET tagId='".$properties['tagId']."',
1394                  name='".$properties['name']."',
1395                  translatedName='".$properties['name']."'
1396              WHERE numId='$id';";
1397        $result=pwg_query($sql);
1398
1399        $sql="DELETE FROM ".$this->tables['user_tags_def']."
1400              WHERE numId='$id';";
1401        $result=pwg_query($sql);
1402
1403        $sql="DELETE FROM ".$this->tables['images_tags']."
1404              WHERE numId='$id';";
1405        $result=pwg_query($sql);
1406
1407        if($currentTagId!='' and $currentTagId!=$properties['tagId'])
1408        {
1409          $sql="UPDATE ".$this->tables['selected_tags']."
1410                SET tagId='".$properties['tagId']."'
1411                WHERE tagId='$currentTagId'";
1412          $result=pwg_query($sql);
1413        }
1414      }
1415
1416      $inserts=array();
1417      foreach($properties['rules'] as $rule)
1418      {
1419        //print_r($rule['value']);
1420        $inserts[]="('$id', '".$rule['defId']."', '".$rule['parentId']."', '".$rule['order']."', '".$rule['type']."', '".$rule['value']."', '".$rule['conditionType']."', '".$rule['conditionValue']."')";
1421      }
1422      $sql="INSERT INTO ".$this->tables['user_tags_def']."
1423            VALUES ".implode(',', $inserts);
1424      $result=pwg_query($sql);
1425
1426      if($this->config['amd_InterfaceMode']=='advanced')
1427      {
1428        $nbImg=$this->buildUserDefinedTags($id);
1429      }
1430      else
1431      {
1432        $nbImg=0;
1433      }
1434
1435      $this->makeStatsConsolidation();
1436
1437      return($id.','.$nbImg);
1438    }
1439
1440
1441    /**
1442     * delete a userDefined tag
1443     *
1444     * @param String $id :
1445     * @return String : ok or ko
1446     */
1447    private function ajax_amd_admin_userDefinedDeleteTag($id)
1448    {
1449      $tagId='';
1450      $sql="SELECT tagId
1451            FROM ".$this->tables['used_tags']."
1452            WHERE numId='$id';";
1453      $result=pwg_query($sql);
1454      if($result)
1455      {
1456        while($row=pwg_db_fetch_assoc($result))
1457        {
1458          $tagId=$row['tagId'];
1459        }
1460      }
1461
1462      if($tagId!='')
1463      {
1464        $sql="DELETE FROM ".$this->tables['selected_tags']."
1465              WHERE tagId='$tagId';";
1466        $result=pwg_query($sql);
1467      }
1468
1469      $sql="DELETE FROM ".$this->tables['used_tags']."
1470            WHERE numId='$id';";
1471      $result=pwg_query($sql);
1472
1473      $sql="DELETE FROM ".$this->tables['user_tags_label']."
1474            WHERE numId='$id';";
1475      $result=pwg_query($sql);
1476
1477      $sql="DELETE FROM ".$this->tables['user_tags_def']."
1478            WHERE numId='$id';";
1479      $result=pwg_query($sql);
1480
1481      $sql="DELETE FROM ".$this->tables['images_tags']."
1482            WHERE numId='$id';";
1483      $result=pwg_query($sql);
1484    }
1485
1486
1487    /**
1488     * return the known values for a given tag id
1489     *
1490     * @param String $id : a tag numId
1491     * @return String : an HTML list ready to use
1492     */
1493    private function ajax_amd_admin_tagGetValues($numId)
1494    {
1495      $returned="";
1496
1497      $sql="SELECT DISTINCT pait.value, COUNT(pait.imageId) AS nbImg, paut.translatable
1498            FROM ".$this->tables['images_tags']." pait
1499              LEFT JOIN ".$this->tables['used_tags']." paut
1500                ON pait.numId=paut.numId
1501            WHERE pait.numId = '$numId'
1502            GROUP BY pait.value
1503            ORDER BY pait.value";
1504      $result=pwg_query($sql);
1505      if($result)
1506      {
1507        while($row=pwg_db_fetch_assoc($result))
1508        {
1509          $value=htmlspecialchars(AMD_root::prepareValueForDisplay($row['value'], ($row['translatable']=='y'), ", "), ENT_QUOTES);
1510          $returned.="<option displayvalue='$value' rawvalue='".$row['value']."'>$value (".$row['nbImg']." ".l10n('images').")</option>";
1511        }
1512      }
1513      return($returned);
1514    }
1515
1516
1517    /**
1518     * return an html list of found keywords in the images_tags table
1519     *
1520     * @return String : html formatted list
1521     */
1522    private function ajax_amd_admin_tagsGetKeywords()
1523    {
1524      global $template;
1525
1526      $returned=array();
1527      $keywordsList=array();
1528      $sql="SELECT DISTINCT pait.value, pait.imageId, paut.numId, paut.tagId
1529            FROM (".$this->tables['images_tags']." pait
1530              JOIN ".$this->tables['used_tags']." paut ON pait.numId = paut.numId)
1531
1532            WHERE (paut.tagId = 'xmp.dc:subject' OR
1533                   paut.tagId = 'xmp.digiKam:TagsList' OR
1534                   paut.tagId = 'xmp.lr:hierarchicalSubject' OR
1535                   paut.tagId = 'iptc.Keywords');";
1536      $result=pwg_query($sql);
1537      if($result)
1538      {
1539        while($row=pwg_db_fetch_assoc($result))
1540        {
1541          if(preg_match('/^a:\d+:{/', $row['value']))
1542          {
1543            /*
1544             *  if value is a serialized string, unserialize and process it
1545             */
1546            $tmp=unserialize($row['value']);
1547            foreach($tmp['values'] as $val)
1548            {
1549              if($row['tagId']=='xmp.digiKam:TagsList' or $row['tagId']=='xmp.lr:hierarchicalSubject')
1550              {
1551                $list=explode($this->tagSeparators[$row['tagId']], $val);
1552                foreach($list as $subTag)
1553                {
1554                  $keywordsList[]="('".mysql_escape_string(trim($subTag))."', ".$row['imageId'].")";
1555                }
1556              }
1557              else
1558              {
1559                $keywordsList[]="('".mysql_escape_string($val)."', ".$row['imageId'].")";
1560              }
1561            }
1562          }
1563          else
1564          {
1565            $keywordsList[]="('".mysql_escape_string($row['value'])."', ".$row['imageId'].")";
1566          }
1567        }
1568
1569        if(count($keywordsList)>0)
1570        {
1571          $sql="CREATE TEMPORARY TABLE amd_temp_tags (
1572                  `value` CHAR(255) default '',
1573                  `imageId` mediumint(8) unsigned NOT NULL default '0',
1574                  PRIMARY KEY  USING BTREE (`value`,`imageId`)
1575                ) CHARACTER SET utf8 COLLATE utf8_general_ci;";
1576          if(pwg_query($sql))
1577          {
1578            $sql="INSERT IGNORE INTO amd_temp_tags
1579              VALUES ".implode(',', $keywordsList);
1580            if(pwg_query($sql))
1581            {
1582              $sql="SELECT att.value AS value,
1583                      COUNT(DISTINCT att.imageId) AS nbPictures,
1584                      IF(ptt.name IS NULL, 'n', 'y') AS tagExists,
1585                      COUNT(DISTINCT pit.image_id) AS nbPicturesTagged
1586                    FROM (amd_temp_tags att LEFT JOIN ".TAGS_TABLE."  ptt ON att.value = ptt.name)
1587                      LEFT JOIN ".IMAGE_TAG_TABLE." pit ON pit.tag_id = ptt.id
1588                    GROUP BY att.value
1589                    HAVING nbPicturesTagged < nbPictures
1590                    ORDER BY att.value";
1591              $result=pwg_query($sql);
1592              if($result)
1593              {
1594                $i=0;
1595                while($row=pwg_db_fetch_assoc($result))
1596                {
1597                  $row['id']=$i;
1598                  $returned[]=$row;
1599                  $i++;
1600                }
1601              }
1602            }
1603          }
1604        }
1605      }
1606
1607      $template->set_filename('keywordsList',
1608                    dirname($this->getFileLocation()).'/admin/amd_metadata_tags_iKeywordsList.tpl');
1609
1610      $template->assign('datas', $returned);
1611      return($template->parse('keywordsList', true));
1612    }
1613
1614
1615    /**
1616     * convert given keywords into tags, and associate them to pictures
1617     *
1618     * @param Array $keywords : an array of strings
1619     * @return String : ok or ko
1620     */
1621    private function ajax_amd_admin_tagsConvertKeywords($keywords)
1622    {
1623      global $template;
1624
1625      $returned='ko';
1626
1627      /*
1628       * 1/ build a temp table with all couple of keywords/imageId
1629       */
1630      $keywordsList=array();
1631      $sql="SELECT DISTINCT pait.value, pait.imageId, paut.numId, paut.tagId
1632            FROM (".$this->tables['images_tags']." pait
1633              JOIN ".$this->tables['used_tags']." paut ON pait.numId = paut.numId)
1634
1635            WHERE (paut.tagId = 'xmp.dc:subject' OR
1636                   paut.tagId = 'xmp.digiKam:TagsList' OR
1637                   paut.tagId = 'xmp.lr:hierarchicalSubject' OR
1638                   paut.tagId = 'iptc.Keywords');";
1639      $result=pwg_query($sql);
1640      if($result)
1641      {
1642        while($row=pwg_db_fetch_assoc($result))
1643        {
1644          if(preg_match('/^a:\d+:{/', $row['value']))
1645          {
1646            /*
1647             *  if value is a serialized string, unserialize and process it
1648             */
1649            $tmp=unserialize($row['value']);
1650            foreach($tmp['values'] as $val)
1651            {
1652              if($row['tagId']=='xmp.digiKam:TagsList')
1653              {
1654                $list=explode($this->tagSeparators[$row['tagId']], $val);
1655                foreach($list as $subTag)
1656                {
1657                  $keywordsList[]="('".mysql_escape_string(trim($subTag))."', ".$row['imageId'].")";
1658                }
1659              }
1660              else
1661              {
1662                $keywordsList[]="('".mysql_escape_string($val)."', ".$row['imageId'].")";
1663              }
1664            }
1665          }
1666          else
1667          {
1668            $keywordsList[]="('".mysql_escape_string($row['value'])."', ".$row['imageId'].")";
1669          }
1670        }
1671        $sql="CREATE TEMPORARY TABLE amd_temp_tags (
1672                `value` CHAR(255) default '',
1673                `imageId` mediumint(8) unsigned NOT NULL default '0',
1674                PRIMARY KEY  USING BTREE (`value`,`imageId`)
1675              ) CHARACTER SET utf8 COLLATE utf8_general_ci;";
1676        if(pwg_query($sql))
1677        {
1678          $sql="INSERT IGNORE INTO amd_temp_tags
1679            VALUES ".implode(',', $keywordsList);
1680          if(pwg_query($sql))
1681          {
1682            foreach($keywords as $key => $val)
1683            {
1684              $keywords[$key]="(att.value LIKE '".mysql_escape_string($val)."')";
1685            }
1686            /*
1687             * 2/ join temp table with piwigo tags table, found the keywords
1688             *    that don't have a corresponding tag
1689             */
1690            $sql="SELECT DISTINCT att.value
1691                  FROM amd_temp_tags att LEFT JOIN ".TAGS_TABLE." ptt ON att.value = ptt.name
1692                  WHERE ptt.id IS NULL
1693                    AND (".implode(' OR ', $keywords).") ";
1694            $result=pwg_query($sql);
1695            if($result)
1696            {
1697              $sql=array();
1698              while($row=pwg_db_fetch_assoc($result))
1699              {
1700                $sql[]="('', '".mysql_escape_string($row['value'])."', '".mysql_escape_string(str2url($row['value']))."')";
1701              }
1702              if(count($sql)>0)
1703              {
1704                $sql="INSERT INTO ".TAGS_TABLE." VALUES ".implode(',', $sql);
1705                pwg_query($sql);
1706              }
1707            }
1708
1709            /*
1710             * 3/ join temp table with piwigo tags table, associate piwigo tagId
1711             *    to the keywords (at this step, all keyword can be associated
1712             *    with a piwigo tagId)
1713             */
1714            $sql="INSERT IGNORE INTO ".IMAGE_TAG_TABLE."
1715                    SELECT DISTINCT att.imageId, ptt.id
1716                    FROM amd_temp_tags att LEFT JOIN ".TAGS_TABLE." ptt ON att.value = ptt.name
1717                    WHERE ".implode(' OR ', $keywords);
1718            $result=pwg_query($sql);
1719            $returned='ok';
1720          }
1721        }
1722      }
1723      return($returned);
1724    }
1725
1726
1727    /**
1728     * set value(s) for option(s)
1729     *
1730     * @param Array or String $ids : a string or an array of string (id)
1731     * @param Array or String $values : a string or an array of string
1732     * @return String : ok or ko
1733     */
1734    private function ajax_amd_admin_configSetOption($ids, $values)
1735    {
1736      if(is_array($ids) and is_array($values) and count($ids)==count($values))
1737      {
1738        foreach($ids as $key=>$id)
1739        {
1740          if(isset($id, $this->config))
1741          {
1742            $this->config[$id]=$values[$key];
1743          }
1744        }
1745        $this->saveConfig();
1746        return('ok');
1747      }
1748      elseif(is_string($ids) and is_string($values))
1749      {
1750        if(isset($ids, $this->config))
1751        {
1752          $this->config[$ids]=$values;
1753        }
1754        $this->saveConfig();
1755        return('ok');
1756      }
1757
1758      return('ko');
1759    }
1760
1761
1762  } //class
1763
1764
1765  $returned=new AMD_ajax($prefixeTable, __FILE__);
1766?>
Note: See TracBrowser for help on using the repository browser.