source: extensions/AMetaData/amd_ajax.php @ 7443

Revision 7443, 55.7 KB checked in by grum, 9 years ago (diff)

fix bug bug:1968
implement feature bug:1912

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