source: extensions/ColorStat/cstat_aip.class.inc.php @ 6258

Last change on this file since 6258 was 6258, checked in by grum, 14 years ago

Version 1.0.1
fix bug:1657

  • Property svn:executable set to *
File size: 21.6 KB
Line 
1<?php
2/* -----------------------------------------------------------------------------
3  Plugin     : ColorStat
4  Author     : Grum
5    email    : grum@piwigo.org
6    website  : http://photos.grum.fr
7
8    << May the Little SpaceFrog be with you ! >>
9  ------------------------------------------------------------------------------
10  See main.inc.php for release information
11
12  CStat_AIP : classe to manage plugin admin pages
13
14  --------------------------------------------------------------------------- */
15
16if(!defined('PHPWG_ROOT_PATH')) die('Hacking attempt!');
17
18include_once('cstat_root.class.inc.php');
19include_once(PHPWG_PLUGINS_PATH.'GrumPluginClasses/classes/GPCTables.class.inc.php');
20include_once(PHPWG_PLUGINS_PATH.'GrumPluginClasses/classes/GPCTabSheet.class.inc.php');
21include_once(PHPWG_PLUGINS_PATH.'GrumPluginClasses/classes/GPCRequestBuilder.class.inc.php');
22include_once(PHPWG_ROOT_PATH.'admin/include/tabsheet.class.php');
23
24class CStat_AIP extends CStat_root
25{
26  protected $tabsheet;
27
28  public function __construct($prefixeTable, $filelocation)
29  {
30    parent::__construct($prefixeTable, $filelocation);
31    $this->checkRequest();
32
33    $this->loadConfig();
34    $this->initEvents();
35
36    $this->tabsheet = new tabsheet();
37    $this->tabsheet->add('database',
38                          l10n('cstat_database'),
39                          $this->getAdminLink()."&amp;f_tabsheet=database");
40    $this->tabsheet->add('stat',
41                          l10n('cstat_stat'),
42                          $this->getAdminLink()."&amp;f_tabsheet=stat");
43    $this->tabsheet->add('search',
44                          l10n('cstat_search'),
45                          $this->getAdminLink()."&amp;f_tabsheet=search");
46    $this->tabsheet->add('config',
47                          l10n('cstat_config'),
48                          $this->getAdminLink()."&amp;f_tabsheet=config");
49  }
50
51  public function __destruct()
52  {
53    unset($this->tabsheet);
54    parent::__destruct();
55  }
56
57  /*
58    initialize events call for the plugin
59  */
60  public function initEvents()
61  {
62    parent::initEvents();
63    if($_REQUEST['f_tabsheet']=='search')
64    {
65      // load request builder JS only on the search page
66      GPCRequestBuilder::loadJSandCSS();
67    }
68    add_event_handler('loc_end_page_header', array(&$this->css, 'applyCSS'));
69    GPCCss::applyGpcCss();
70  }
71
72  /*
73    display administration page
74  */
75  public function manage()
76  {
77    global $template;
78
79    $this->returnAjaxContent();
80
81    $template->set_filename('plugin_admin_content', dirname(__FILE__)."/admin/cstat_admin.tpl");
82
83
84    switch($_REQUEST['f_tabsheet'])
85    {
86      case 'database':
87        $this->displayDatabasePage();
88        break;
89      case 'stat':
90        $this->displayStatPage();
91        break;
92      case 'search':
93        $this->displaySearchPage();
94        break;
95      case 'config':
96        $this->displayConfigPage();
97        break;
98    }
99
100    $this->tabsheet->select($_REQUEST['f_tabsheet']);
101    $this->tabsheet->assign();
102    $selected_tab=$this->tabsheet->get_selected();
103    $template->assign($this->tabsheet->get_titlename(), "[".$selected_tab['caption']."]");
104
105    $template_plugin["CSTAT_VERSION"] = "<i>".$this->getPluginName()."</i> ".l10n('cstat_release').CSTAT_VERSION;
106
107    $template->assign('plugin', $template_plugin);
108    $template->assign_var_from_handle('ADMIN_CONTENT', 'plugin_admin_content');
109  }
110
111
112  /*
113    return ajax content
114  */
115  protected function returnAjaxContent()
116  {
117    global $ajax, $template;
118
119    if(isset($_REQUEST['ajaxfct']))
120    {
121      //$this->debug("AJAXFCT:".$_REQUEST['ajaxfct']);
122      $result="<p class='errors'>An error has occured</p>";
123      switch($_REQUEST['ajaxfct'])
124      {
125        case 'updateDatabaseGetStatus':
126          $result=$this->ajax_cstat_updateDatabaseGetStatus();
127          break;
128        case 'updateDatabaseGetList':
129          $result=$this->ajax_cstat_updateDatabaseGetList($_REQUEST['selectMode'], $_REQUEST['numOfItems']);
130          break;
131        case 'updateDatabaseDoAnalyze':
132          $result=$this->ajax_cstat_updateDatabaseDoAnalyze($_REQUEST['imagesList']);
133          break;
134        case 'updateDatabaseConsolidation':
135          $result=$this->ajax_cstat_updateDatabaseConsolidation();
136          break;
137        case 'showStatsGetListColors':
138          $result=$this->ajax_cstat_showStatsGetListColors($_REQUEST['orderType']);
139          break;
140        case 'doPpsBench':
141          $result=$this->ajax_cstat_ppsBench($_REQUEST['quality'], true);
142          break;
143      }
144      GPCAjax::returnResult($result);
145    }
146  }
147
148  /**
149   * check the $_REQUEST values and set default values
150   *
151   */
152  protected function checkRequest()
153  {
154    if(!isset($_REQUEST['f_tabsheet'])) $_REQUEST['f_tabsheet']='stat';
155
156
157    if(!($_REQUEST['f_tabsheet']=='database' or
158         $_REQUEST['f_tabsheet']=='stat' or
159         $_REQUEST['f_tabsheet']=='search' or
160         $_REQUEST['f_tabsheet']=='config')) $_REQUEST['f_tabsheet']='stat';
161
162
163    if(isset($_REQUEST['ajaxfct']))
164    {
165      if($_REQUEST['ajaxfct']=='updateDatabaseGetList')
166      {
167        if(!isset($_REQUEST['selectMode'])) $_REQUEST['selectMode']='caddieAdd';
168        if(!isset($_REQUEST['numOfItems'])) $_REQUEST['numOfItems']=$this->config['analyze_itemPerRequest'];
169
170        if(!($_REQUEST['selectMode']=='notAnalyzed' or
171             $_REQUEST['selectMode']=='all' or
172             $_REQUEST['selectMode']=='caddieAdd' or
173             $_REQUEST['selectMode']=='caddieReplace')) $_REQUEST['selectMode']='caddieAdd';
174
175        if($_REQUEST['numOfItems'] <=0 or $_REQUEST['numOfItems']>100) $_REQUEST['numOfItems']=10;
176      }
177
178
179      if($_REQUEST['ajaxfct']=='updateDatabaseDoAnalyze')
180      {
181        if(!isset($_REQUEST['imagesList'])) $_REQUEST['imagesList']='';
182      }
183
184      if($_REQUEST['ajaxfct']=='showStatsGetListColors')
185      {
186        if(!isset($_REQUEST['orderType'])) $_REQUEST['orderType']='img';
187
188        if(!($_REQUEST['orderType']=='color' or
189             $_REQUEST['orderType']=='img' or
190             $_REQUEST['orderType']=='pixels')) $_REQUEST['orderType']=='img';
191      }
192
193
194      if($_REQUEST['ajaxfct']=='doPpsBench')
195      {
196        if(!isset($_REQUEST['quality'])) $_REQUEST['quality']=8;
197        if($_REQUEST['quality']>50 or $_REQUEST['quality']<1) $_REQUEST['quality']=8;
198      }
199    }
200
201  }
202
203  /**
204   * display the database page
205   */
206  protected function displayDatabasePage()
207  {
208    global $template;
209
210    $template->set_filename('body_page',
211                dirname($this->getFileLocation()).'/admin/cstat_database.tpl');
212
213    $datas=Array(
214      'urlRequest' => $this->getAdminLink(),
215      'numberOfItemsPerRequest' => $this->config['analyze_itemPerRequest']
216    );
217    $template->assign('datas', $datas);
218    $template->assign_var_from_handle('CSTAT_BODY_PAGE', 'body_page');
219  } //displayDatabasePage
220
221  /**
222   * display the stat page
223   */
224  protected function displayStatPage()
225  {
226    global $template;
227
228    $template->set_filename('body_page',
229                dirname($this->getFileLocation()).'/admin/cstat_stat.tpl');
230
231    $colorTable=CStat_functions::getColorTableWithStat();
232
233
234    $datas=Array(
235      //'themeconf' => Array('name' => $template->get_themeconf('name')),
236      'colorTable' => CStat_functions::htmlColorTable(
237                        $colorTable,
238                        ($this->config['analyze_colorTable']=='small')?19:10,
239                        "",
240                        "color0px",
241                        "<br>"
242                      ),
243      'urlRequest' => $this->getAdminLink(),
244      'config_GetListColors_OrderType' => $this->config['display_stat_orderType'],
245    );
246    $template->assign('datas', $datas);
247    $template->assign_var_from_handle('CSTAT_BODY_PAGE', 'body_page');
248  } //displayStatPage
249
250
251  /**
252   * display search page
253   */
254  protected function displaySearchPage()
255  {
256    global $template, $lang;
257
258    $template->set_filename('body_page',
259                dirname($this->getFileLocation()).'/admin/cstat_search.tpl');
260
261    $template->assign('cstat_search_page', GPCRequestBuilder::displaySearchPage());
262
263    $template->assign_var_from_handle('CSTAT_BODY_PAGE', 'body_page');
264  } //displaySearchPage
265
266
267  /**
268   * manage display of config page & save config
269   */
270  protected function displayConfigPage()
271  {
272    $tmpPct=$this->config['stat_minPct'];
273
274    if(!$this->adviser_abort())
275    {
276      if(isset($_POST['submit_save_config']))
277      {
278        foreach($this->config as $key => $val)
279        {
280          if(isset($_REQUEST['f_'.$key]))
281          {
282            $this->config[$key] = $_REQUEST['f_'.$key];
283          }
284        }
285        $this->displayResult(l10n('cstat_save_config'), $this->saveConfig());
286      }
287    }
288
289    if($tmpPct!=$this->config['stat_minPct'])
290    {
291      $this->updateDatabaseConsolidation();
292    }
293
294    $this->displayConfig();
295  }
296
297  /**
298   * display config page
299   */
300  protected function displayConfig()
301  {
302    global $template, $lang;
303
304    $configTabs=new GPCTabSheet('configTabsheet', $this->tabsheet->get_titlename(), 'tabsheet2 gcBorder', 'itab2');
305    $configTabs->add('database',
306                      l10n('cstat_database'),
307                      '', true, "displayConfig('database');");
308    $configTabs->add('statsearch',
309                      l10n('cstat_stat_and_search'),
310                      '', false, "displayConfig('statsearch');");
311    $configTabs->add('display',
312                      l10n('cstat_gallery_integration'),
313                      '', false, "displayConfig('display');");
314    $configTabs->assign();
315
316    $template->set_filename('body_page',
317                dirname($this->getFileLocation()).'/admin/cstat_config.tpl');
318
319    $nbPictures=0;
320    $sql="SELECT COUNT(image_id) FROM ".$this->tables['images'];
321    $result=pwg_query($sql);
322    if($result)
323    {
324      while($row=pwg_db_fetch_row($result))
325      {
326        $nbPictures=$row[0];
327      }
328    }
329
330
331    $datas=Array(
332      'nbPictures' => $nbPictures,
333      'pps' => $this->config['analyze_pps'],
334      'quality' => $this->config['analyze_ppsQuality'],
335      'qualityHighest' => 14000,
336      'qualityHigh' => 7500,
337      'qualityNormal' => 3500,
338      'qualityLow' => 1200,
339      'qualityLowest' => 600,
340      'urlRequest' => $this->getAdminLink(),
341      'minPct' => $this->config['stat_minPct'],
342      'showColors' => $this->config['display_gallery_showColors'],
343      'colorSize' => $this->config['display_gallery_colorSize'],
344    );
345
346    $template->assign('datas', $datas);
347
348    $template->assign_var_from_handle('CSTAT_BODY_PAGE', 'body_page');
349  } //displayConfig
350
351
352  /**
353   * manage adviser profile
354   * return true if user is adviser
355   */
356  protected function adviser_abort()
357  {
358    if(is_adviser())
359    {
360      $this->displayResult(l10n("cstat_adviser_not_allowed"), false);
361      return(true);
362    }
363    return(false);
364  }
365
366
367  /* ---------------------------------------------------------------------------
368    function to manage database manipulation
369  --------------------------------------------------------------------------- */
370  protected function analyzeImageFile($fileName, $imageId, $colorTable)
371  {
372    // set the picture to the 'try to analyze' statut
373    $sql="UPDATE ".$this->tables['images']." SET analyzed='t'
374          WHERE image_id=".$imageId.";";
375    pwg_query($sql);
376
377    $colors=ColorStat::getFileColors(
378      $fileName,
379      $colorTable,
380      Array(
381        'mode' => 'numAnalyzed',
382        'numColors' => 24,
383        'numAnalyzed' => $this->config['analyze_ppsQuality'],
384      )
385    );
386
387    if($colors!==false and
388       ColorStat::$fileColorsStat['colors']>0 and
389       ColorStat::$fileColorsStat['analyzed']>0)
390    {
391      $sql="UPDATE ".$this->tables['images']."
392              SET analyzed='y',
393                  num_colors='".ColorStat::$fileColorsStat['colors']."',
394                  num_pixels='".ColorStat::$fileColorsStat['pixels']."',
395                  analyzed_pixels='".ColorStat::$fileColorsStat['analyzed']."',
396                  pps='".ColorStat::$fileColorsStat['pps']."',
397                  time='".ColorStat::$fileColorsStat['time']."',
398                  quality='".ColorStat::$fileColorsStat['quality']."'
399            WHERE image_id=".$imageId.";";
400      pwg_query($sql);
401      $sql="";
402      foreach($colors as $key=>$val)
403      {
404        /*
405         * $key => RGB color #RRGGBB
406         * $val => Array (
407         *            'hsv' => Array ('H', 'S', 'V')
408         *            'num' => integer
409         *            'pct' => float
410         *          )
411         */
412
413        $sql.=(($sql=="")?"":", ")."
414              ('".$imageId."', '".$key."', ".$val['pct'].", ".$val['num'].")";
415      }
416      $sql="REPLACE INTO ".$this->tables['images_colors']."
417                VALUES ".$sql;
418      pwg_query($sql);
419
420      return($imageId.'='.ColorStat::$fileColorsStat['colors'].';');
421    }
422    else
423    {
424      return($imageId.'=KO;');
425    }
426  }
427
428
429  /**
430   * make consolidation for the color_table :
431   *  - count number of images using a color
432   *  - count number of pixels of a color
433   */
434  protected function updateDatabaseConsolidation()
435  {
436    $sql="UPDATE ".$this->tables['color_table']." cct
437          SET cct.num_images=0,
438              cct.num_pixels=0;";
439    pwg_query($sql);
440
441    $sql="UPDATE ".$this->tables['color_table']." cct,
442                 (SELECT color_id,
443                         count(image_id) AS num_images,
444                         sum(num_pixels) AS num_pixels
445                  FROM ".$this->tables['images_colors']."
446                  WHERE pct >= ".$this->config['stat_minPct']."
447                  GROUP BY color_id) cic
448          SET cct.num_images=cic.num_images,
449              cct.num_pixels=cic.num_pixels
450          WHERE cct.color_id=cic.color_id;";
451    pwg_query($sql);
452
453    $sql="UPDATE ".$this->tables['images']." pci
454          SET pci.colors = '',
455              pci.colors_pct = ''";
456    pwg_query($sql);
457
458    $sql="UPDATE ".$this->tables['images']." pci,
459          (SELECT image_id,
460                  GROUP_CONCAT(color_id ORDER BY pct DESC SEPARATOR ',') AS colors,
461                  GROUP_CONCAT(pct ORDER BY pct DESC SEPARATOR ',') AS colors_pct
462           FROM ".$this->tables['images_colors']."
463           WHERE pct >= ".$this->config['stat_minPct']."
464           GROUP BY image_id) pcic
465          SET pci.colors = pcic.colors,
466              pci.colors_pct = pcic.colors_pct
467          WHERE pci.image_id = pcic.image_id;";
468    pwg_query($sql);
469  }
470
471  /* ---------------------------------------------------------------------------
472    ajax functions
473  --------------------------------------------------------------------------- */
474
475  /**
476   * returns a list of formated string, separated with a semi-colon :
477   *  - number of current analyzed pictures
478   *  - number of pictures not analyzed + number of picture in error
479   *
480   * @return String
481   */
482  private function ajax_cstat_updateDatabaseGetStatus()
483  {
484    $numOfPictures=0;
485    $numOfPicturesNotAnalyzed=0;
486    $numOfPicturesInError=0;
487
488    $sql="SELECT COUNT(image_id), analyzed FROM ".$this->tables['images']."
489            GROUP BY analyzed;";
490    $result=pwg_query($sql);
491    if($result)
492    {
493      while($row=pwg_db_fetch_row($result))
494      {
495        switch($row[1])
496        {
497          case 'n': //no
498            $numOfPicturesNotAnalyzed=$row[0];
499            break;
500          case 'y': //yes
501            $numOfPictures=$row[0];
502            break;
503          case 't': //tried to be analyzed, but not finished
504            $numOfPicturesInError=$row[0];
505            break;
506        }
507      }
508    }
509
510    return(sprintf(l10n("cstat_numberOfAnalyzedPictures"), $numOfPictures).";".
511           sprintf(l10n("cstat_numberOfNotAnalyzedPictures"), $numOfPicturesNotAnalyzed).";".
512           sprintf(l10n("cstat_numberOfPicturesInError"), $numOfPicturesInError));
513  }
514
515
516  /**
517   * return a list of picture Id
518   *
519   * picture id are separated with a space " "
520   * picture id are grouped in blocks of 'NumberOfItemsPerRequest' items and
521   * are separated with a semi-colon ";"
522   *
523   * client side just have to split blocks, and transmit it to the server
524   *
525   * There is four mode to determine the pictures being analyzed :
526   *  - "all"           : analyze all the images (add & replace)
527   *  - "notAnalyzed"   : analyze only the images not yet analyzed (add)
528   *  - "caddieAdd"     : analyze all the images of the caddie (add)
529   *  - "caddieReplace" : analyze all the images of the caddie (add & replace)
530   *
531   * @param String $mode
532   * @param Integer $nbOfItems : number of items per request
533   * @return String : list of image id to be analyzed, separated with a space
534   *                      "23 78 4523 5670"
535   */
536  private function ajax_cstat_updateDatabaseGetList($mode, $nbOfItems)
537  {
538    global $user;
539
540    $returned="";
541
542    $sql="SELECT cit.image_id FROM ".$this->tables['images']." cit";
543    if($mode=="notAnalyzed")
544    {
545      $sql.=" WHERE cit.analyzed='n'";
546    }
547    elseif($mode=="caddieAdd" or $mode=="caddieReplace")
548    {
549
550      $sql.=" LEFT JOIN ".CADDIE_TABLE." ct ON cit.image_id = ct.element_id
551            WHERE ct.user_id = ".$user['id']." ";
552      if($mode=="caddieAdd") $sql.=" AND cit.analyzed='n'";
553    }
554
555    if($mode=="all" or $mode=="caddieReplace")
556    {
557      pwg_query("UPDATE ".$this->tables['images']."
558                  SET analyzed='n',
559                      num_colors=0,
560                      num_pixels=0,
561                      analyzed_pixels=0,
562                      pps=0,
563                      time=0,
564                      quality=0
565                  WHERE analyzed<>'t'");
566      pwg_query("DELETE FROM ".$this->tables['images_colors']);
567      pwg_query("UPDATE ".$this->tables['color_table']."
568                 SET num_pixels=0, num_images=0;");
569    }
570
571    $result=pwg_query($sql);
572    if($result)
573    {
574      $i=0;
575      while($row=pwg_db_fetch_row($result))
576      {
577        $returned.=$row[0];
578        $i++;
579        if($i>=$nbOfItems)
580        {
581          $returned.=";";
582          $i=0;
583        }
584        else
585        {
586          $returned.=" ";
587        }
588      }
589    }
590    return(trim($returned).";");
591  }
592
593
594
595  /**
596   * extract metadata from images
597   *
598   * @param String $imageList : list of image id to be analyzed, separated with
599   *                            a space
600   *                                "23 78 4523 5670"
601   * @return String : list of the analyzed pictures, with number of colors found
602   *                  for each picture
603   *                    "23=0;78=66;4523=33;5670=91;"
604   */
605  private function ajax_cstat_updateDatabaseDoAnalyze($imagesList)
606  {
607    $list=explode(" ", trim($imagesList));
608
609    $returned="";
610
611    if(count($list)>0 and trim($imagesList)!='')
612    {
613      // $path = path of piwigo's on the server filesystem
614      $path=dirname(dirname(dirname(__FILE__)));
615
616      $sql="SELECT id, path FROM ".IMAGES_TABLE." WHERE id IN (".implode(", ", $list).")";
617      $result=pwg_query($sql);
618      if($result)
619      {
620        $colorTable=ColorStat::getColorTable(
621          CStat_root::$colorTableSize[$this->config['analyze_colorTable']][0],
622          CStat_root::$colorTableSize[$this->config['analyze_colorTable']][1]
623        );
624
625        while($row=pwg_db_fetch_assoc($result))
626        {
627          /*
628           * in some case (in a combination of some pictures), when there is too
629           * much pictures to analyze in the same request, a fatal error occurs
630           * with the message : "Allowed memory size of XXXXX bytes exhausted"
631           *
632           *
633           * tracking memory leak is not easy... :-(
634           *
635           */
636          //echo "analyzing:".$row['id']."\n";
637          //$mem1=memory_get_usage();
638          //echo "memory before analyze:".$mem1."\n";
639          $returned.=$this->analyzeImageFile($path."/".$row['path'], $row['id'], $colorTable);
640          //echo $returned."\n";
641          //$mem2=memory_get_usage();
642          //echo "memory after analyze:".$mem2." (".($mem2-$mem1).")\n";
643        }
644      }
645    }
646    return($returned);
647  }
648
649
650  /**
651   * make consolidation for the color_table :
652   *  - count number of images using a color
653   *  - count number of pixels of a color
654   */
655  private function ajax_cstat_updateDatabaseConsolidation()
656  {
657    $this->updateDatabaseConsolidation();
658    return("ok");
659  }
660
661
662
663  /**
664   * return a formatted <table> (using the template "cstat_stat_show_iListColors")
665   * of used tag with, for each tag, the number and the percentage of pictures
666   * where the tag was found
667   *
668   * @param String $orderType : order for the list (by color 'color' or by number
669   *                            of pictures 'img' or by number of pixels 'pixels')
670   * @return String
671   */
672  private function ajax_cstat_showStatsGetListColors($orderType)
673  {
674    global $template;
675
676    $this->config['display_stat_orderType'] = $orderType;
677    $this->saveConfig();
678
679    $local_tpl = new Template(CSTAT_PATH."admin/", "");
680    $local_tpl->set_filename('body_page',
681                  dirname($this->getFileLocation()).'/admin/cstat_stat_show_iListColors.tpl');
682
683    $generalStats=CStat_functions::getGeneralStats();
684
685    $sql="SELECT color_id, num_images, num_pixels
686          FROM ".$this->tables['color_table']."
687          WHERE num_images > 0 ";
688    if($orderType=='color')
689    {
690      $sql.=" ORDER BY hue ASC, saturation ASC, value DESC";
691    }
692    elseif($orderType=='img')
693    {
694      $sql.=" ORDER BY num_images DESC, num_pixels DESC ";
695    }
696    elseif($orderType=='pixels')
697    {
698      $sql.=" ORDER BY num_pixels DESC, num_images DESC ";
699    }
700
701    $datas=Array();
702    $result=pwg_query($sql);
703    if($result)
704    {
705      while($row=pwg_db_fetch_assoc($result))
706      {
707        $row['pct_images']=sprintf('%.2f', round(100*$row['num_images']/$generalStats['nbImages'],2));
708        $row['pct_pixels']=sprintf('%.2f', round(100*$row['num_pixels']/$generalStats['pixelsAnalyzedSum'],2));
709        $datas[]=$row;
710      }
711    }
712
713    $local_tpl->assign('themeconf', Array('name' => $template->get_themeconf('name')));
714    $local_tpl->assign('datas', $datas);
715
716    return($local_tpl->parse('body_page', true));
717  }
718
719} //class
720
721
722?>
Note: See TracBrowser for help on using the repository browser.