source: extensions/AMetaData/amd_ajax.php @ 29805

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