source: extensions/AMetaData/amd_ajax.php @ 7677

Revision 7677, 56.7 KB checked in by grum, 9 years ago (diff)

fix bug:2015 - Can't add a new personnal tag
fix bug:2017 - MySQL 5.1 incompatibility

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