source: extensions/AMetaData/amd_ajax.php @ 15343

Last change on this file since 15343 was 15343, checked in by grum, 12 years ago

feature:2637 - Compatibility with Piwigo 2.4

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