source: trunk/admin/update.php @ 659

Last change on this file since 659 was 659, checked in by plg, 19 years ago
  • admin/update : filesystem synchronization process completely rewritten. How to speed up sync ? by avoiding recursivity !
  • admin/update : option to display verbose information details
  • admin/update : option to simulate only. No database insert, delete or update will be made
  • bug fixed : in admin/cat_list, if you delete a virtual category, you may create a gap in the rank list. This gap will generate errors when trying to move a category on this gap. Fixed by calling ordering and update_global_rank at category deletion.
  • admin/cat_list, only one query to insert a new virtual category (no need of a second query to update uppercats and global_rank)
  • for a given category, even if empty, the representing element must not be the one of a forbidden category for the current user
  • generation time optionnaly displayed on the bottom of each page becomes more price : number of SQL queries and SQL time added.
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 19.3 KB
Line 
1<?php
2// +-----------------------------------------------------------------------+
3// | PhpWebGallery - a PHP based picture gallery                           |
4// | Copyright (C) 2002-2003 Pierrick LE GALL - pierrick@phpwebgallery.net |
5// | Copyright (C) 2003-2004 PhpWebGallery Team - http://phpwebgallery.net |
6// +-----------------------------------------------------------------------+
7// | branch        : BSF (Best So Far)
8// | file          : $RCSfile$
9// | last update   : $Date: 2004-12-27 14:30:49 +0000 (Mon, 27 Dec 2004) $
10// | last modifier : $Author: plg $
11// | revision      : $Revision: 659 $
12// +-----------------------------------------------------------------------+
13// | This program is free software; you can redistribute it and/or modify  |
14// | it under the terms of the GNU General Public License as published by  |
15// | the Free Software Foundation                                          |
16// |                                                                       |
17// | This program is distributed in the hope that it will be useful, but   |
18// | WITHOUT ANY WARRANTY; without even the implied warranty of            |
19// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU      |
20// | General Public License for more details.                              |
21// |                                                                       |
22// | You should have received a copy of the GNU General Public License     |
23// | along with this program; if not, write to the Free Software           |
24// | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
25// | USA.                                                                  |
26// +-----------------------------------------------------------------------+
27
28if (!defined('PHPWG_ROOT_PATH'))
29{
30  die ('Hacking attempt!');
31}
32include_once( PHPWG_ROOT_PATH.'admin/include/isadmin.inc.php');
33
34define('CURRENT_DATE', date('Y-m-d'));
35$error_labels = array('PWG-UPDATE-1' => $lang['update_wrong_dirname_short'],
36                      'PWG-UPDATE-2' => $lang['update_missing_tn_short']);
37$errors = array();
38$infos = array();
39// +-----------------------------------------------------------------------+
40// |                      directories / categories                         |
41// +-----------------------------------------------------------------------+
42if (isset($_POST['submit'])
43    and ($_POST['sync'] == 'dirs' or $_POST['sync'] == 'files'))
44{
45  $counts['new_categories'] = 0;
46  $counts['del_categories'] = 0;
47  $counts['del_elements'] = 0;
48  $counts['new_elements'] = 0;
49
50  // shall we simulate only
51  if (isset($_POST['simulate']) and $_POST['simulate'] == 1)
52  {
53    $simulate = true;
54  }
55  else
56  {
57    $simulate = false;
58  }
59 
60  $start = get_moment();
61  // which categories to update ?
62  $cat_ids = array();
63
64  $query = '
65SELECT id, uppercats, global_rank, status, visible
66  FROM '.CATEGORIES_TABLE.'
67  WHERE dir IS NOT NULL
68    AND site_id = 1';
69  if (isset($_POST['cat']) and is_numeric($_POST['cat']))
70  {
71    if (isset($_POST['subcats-included']) and $_POST['subcats-included'] == 1)
72    {
73      $query.= '
74    AND uppercats REGEXP \'(^|,)'.$_POST['cat'].'(,|$)\'
75';
76    }
77    else
78    {
79      $query.= '
80    AND id = '.$_POST['cat'].'
81';
82    }
83  }
84  $query.= '
85;';
86  $result = pwg_query($query);
87
88  $db_categories = array();
89  while ($row = mysql_fetch_array($result))
90  {
91    $db_categories[$row['id']] = $row;
92  }
93
94  // get categort full directories in an array for comparison with file
95  // system directory tree
96  $db_fulldirs = get_fulldirs(array_keys($db_categories));
97 
98  // what is the base directory to search file system sub-directories ?
99  if (isset($_POST['cat']) and is_numeric($_POST['cat']))
100  {
101    $basedir = $db_fulldirs[$_POST['cat']];
102  }
103  else
104  {
105    $query = '
106SELECT galleries_url
107  FROM '.SITES_TABLE.'
108  WHERE id = 1
109;';
110    list($galleries_url) = mysql_fetch_array(pwg_query($query));
111    $basedir = preg_replace('#/*$#', '', $galleries_url);
112  }
113
114  // we need to have fulldirs as keys to make efficient comparison
115  $db_fulldirs = array_flip($db_fulldirs);
116
117  // finding next rank for each id_uppercat
118  $query = '
119SELECT id_uppercat, MAX(rank)+1 AS next_rank
120  FROM '.CATEGORIES_TABLE.'
121  GROUP BY id_uppercat
122;';
123  $result = pwg_query($query);
124  while ($row = mysql_fetch_array($result))
125  {
126    // for the id_uppercat NULL, we write 'NULL' and not the empty string
127    if (!isset($row['id_uppercat']) or $row['id_uppercat'] == '')
128    {
129      $row['id_uppercat'] = 'NULL';
130    }
131    $next_rank[$row['id_uppercat']] = $row['next_rank'];
132  }
133 
134  // next category id available
135  $query = '
136SELECT MAX(id)+1 AS next_id
137  FROM '.CATEGORIES_TABLE.'
138;';
139  list($next_id) = mysql_fetch_array(pwg_query($query));
140
141  // retrieve file system sub-directories fulldirs
142  $fs_fulldirs = get_fs_directories($basedir);
143 
144  $inserts = array();
145  // new categories are the directories not present yet in the database
146  foreach (array_diff($fs_fulldirs, array_keys($db_fulldirs)) as $fulldir)
147  {
148    $dir = basename($fulldir);
149    if (preg_match('/^[a-zA-Z0-9-_.]+$/', $dir))
150    {
151      $insert = array();
152     
153      $insert{'id'} = $next_id++;
154      $insert{'dir'} = $dir;
155      $insert{'name'} = str_replace('_', ' ', $dir);
156      $insert{'site_id'} = 1;
157      $insert{'commentable'} = $conf['newcat_default_commentable'];
158      $insert{'uploadable'} = $conf['newcat_default_uploadable'];
159      $insert{'status'} = $conf{'newcat_default_status'};
160      $insert{'visible'} = $conf{'newcat_default_visible'};
161
162      if (isset($db_fulldirs[dirname($fulldir)]))
163      {
164        $parent = $db_fulldirs[dirname($fulldir)];
165
166        $insert{'id_uppercat'} = $parent;
167        $insert{'uppercats'} =
168          $db_categories[$parent]['uppercats'].','.$insert{'id'};
169        $insert{'rank'} = $next_rank[$parent]++;
170        $insert{'global_rank'} =
171          $db_categories[$parent]['global_rank'].'.'.$insert{'rank'};
172        if ('private' == $db_categories[$parent]['status'])
173        {
174          $insert{'status'} = 'private';
175        }
176        if ('false' == $db_categories[$parent]['visible'])
177        {
178          $insert{'visible'} = 'false';
179        }
180      }
181      else
182      {
183        $insert{'uppercats'} = $insert{'id'};
184        $insert{'rank'} = $next_rank['NULL']++;
185        $insert{'global_rank'} = $insert{'rank'};
186      }
187
188      array_push($inserts, $insert);
189      array_push($infos, array('path' => $fulldir,
190                               'info' => $lang['update_research_added']));
191
192      // add the new category to $db_categories and $db_fulldirs array
193      $db_categories[$insert{'id'}] =
194        array(
195          'id' => $insert{'id'},
196          'status' => $insert{'status'},
197          'visible' => $insert{'visible'},
198          'uppercats' => $insert{'uppercats'},
199          'global_rank' => $insert{'global_rank'}
200          );
201      $db_fulldirs[$fulldir] = $insert{'id'};
202      $next_rank[$insert{'id'}] = 1;
203    }
204    else
205    {
206      array_push($errors, array('path' => $fulldir, 'type' => 'PWG-UPDATE-1'));
207    }
208  }
209
210  if (count($inserts) > 0)
211  {
212    if (!$simulate)
213    {
214      $dbfields = array(
215        'id','dir','name','site_id','id_uppercat','uppercats','commentable',
216        'uploadable','visible','status','rank','global_rank'
217        );
218      mass_inserts(CATEGORIES_TABLE, $dbfields, $inserts);
219    }
220   
221    $counts['new_categories'] = count($inserts);
222  }
223
224  // to delete categories
225  $to_delete = array();
226  foreach (array_diff(array_keys($db_fulldirs), $fs_fulldirs) as $fulldir)
227  {
228    array_push($to_delete, $db_fulldirs[$fulldir]);
229    unset($db_fulldirs[$fulldir]);
230    array_push($infos, array('path' => $fulldir,
231                             'info' => $lang['update_research_deleted']));
232  }
233  if (count($to_delete) > 0)
234  {
235    if (!$simulate)
236    {
237      delete_categories($to_delete);
238    }
239    $counts['del_categories'] = count($to_delete);
240  }
241 
242  echo get_elapsed_time($start, get_moment());
243  echo ' for new method scanning directories<br />';
244}
245// +-----------------------------------------------------------------------+
246// |                           files / elements                            |
247// +-----------------------------------------------------------------------+
248if (isset($_POST['submit']) and $_POST['sync'] == 'files')
249{ 
250  $start_files = get_moment();
251  $start= $start_files;
252
253  $fs = get_fs($basedir);
254 
255  echo get_elapsed_time($start, get_moment());
256  echo ' for get_fs<br />';
257 
258  $cat_ids = array_diff(array_keys($db_categories), $to_delete);
259
260  $db_elements = array();
261  $db_unvalidated = array();
262 
263  if (count($cat_ids) > 0)
264  {
265    $query = '
266SELECT id, path
267  FROM '.IMAGES_TABLE.'
268  WHERE storage_category_id IN (
269'.wordwrap(implode(', ', $cat_ids), 80, "\n").')
270;';
271    $result = pwg_query($query);
272    while ($row = mysql_fetch_array($result))
273    {
274      $db_elements[$row['id']] = $row['path'];
275    }
276
277    // searching the unvalidated waiting elements (they must not be taken into
278    // account)
279    $query = '
280SELECT file,storage_category_id
281  FROM '.WAITING_TABLE.'
282  WHERE storage_category_id IN (
283'.wordwrap(implode(', ', $cat_ids), 80, "\n").')
284    AND validated = \'false\'
285;';
286    $result = pwg_query($query);
287    while ($row = mysql_fetch_array($result))
288    {
289      array_push(
290        $db_unvalidated,
291        array_search($row['storage_category_id'],
292                     $db_fulldirs).'/'.$row['file']
293        );
294    }
295  }
296
297  // next element id available
298  $query = '
299SELECT MAX(id)+1 AS next_element_id
300  FROM '.IMAGES_TABLE.'
301;';
302  list($next_element_id) = mysql_fetch_array(pwg_query($query));
303
304  $start = get_moment();
305
306  // because isset is one hundred time faster than in_array
307  $fs['thumbnails'] = array_flip($fs['thumbnails']);
308  $fs['representatives'] = array_flip($fs['representatives']);
309 
310  $inserts = array();
311  $insert_links = array();
312 
313  foreach (array_diff($fs['elements'], $db_elements, $db_unvalidated) as $path)
314  {
315    $insert = array();
316    // storage category must exist
317    $dirname = dirname($path);
318    if (!isset($db_fulldirs[$dirname]))
319    {
320      continue;
321    }
322    $filename = basename($path);
323    if (!preg_match('/^[a-zA-Z0-9-_.]+$/', $filename))
324    {
325      array_push($errors, array('path' => $path, 'type' => 'PWG-UPDATE-1'));
326      continue;
327    }
328
329    // searching the thumbnail
330    $filename_wo_ext = get_filename_wo_extension($filename);
331    $tn_ext = '';
332    $base_test = $dirname.'/thumbnail/';
333    $base_test.= $conf['prefix_thumbnail'].$filename_wo_ext.'.';
334    foreach ($conf['picture_ext'] as $ext)
335    {
336      $test = $base_test.$ext;
337      if (isset($fs['thumbnails'][$test]))
338      {
339        $tn_ext = $ext;
340        break;
341      }
342      else
343      {
344        continue;
345      }
346    }
347
348    // 2 cases : the element is a picture or not. Indeed, for a picture
349    // thumbnail is mandatory and for non picture element, thumbnail and
350    // representative are optionnal
351    if (in_array(get_extension($filename), $conf['picture_ext']))
352    {
353      // if we found a thumnbnail corresponding to our picture...
354      if ($tn_ext != '')
355      {
356        $insert{'id'} = $next_element_id++;
357        $insert{'file'} = $filename;
358        $insert{'storage_category_id'} = $db_fulldirs[$dirname];
359        $insert{'date_available'} = CURRENT_DATE;
360        $insert{'tn_ext'} = $tn_ext;
361        $insert{'path'} = $path;
362
363        array_push($inserts, $insert);
364        array_push($insert_links,
365                   array('image_id' => $insert{'id'},
366                         'category_id' => $insert{'storage_category_id'}));
367        array_push($infos, array('path' => $insert{'path'},
368                                 'info' => $lang['update_research_added']));
369      }
370      else
371      {
372        array_push($errors, array('path' => $path, 'type' => 'PWG-UPDATE-2'));
373      }
374    }
375    else
376    {
377      // searching a representative
378      $representative_ext = '';
379      $base_test = $dirname.'/pwg_representative/'.$filename_wo_ext.'.';
380      foreach ($conf['picture_ext'] as $ext)
381      {
382        $test = $base_test.$ext;
383        if (isset($fs['representatives'][$test]))
384        {
385          $representative_ext = $ext;
386          break;
387        }
388        else
389        {
390          continue;
391        }
392      }
393
394      $insert{'id'} = $next_element_id++;
395      $insert{'file'} = $filename;
396      $insert{'storage_category_id'} = $db_fulldirs[$dirname];
397      $insert{'date_available'} = CURRENT_DATE;
398      $insert{'path'} = $path;
399       
400      if ($tn_ext != '')
401      {
402        $insert{'tn_ext'} = $tn_ext;
403      }
404      if ($representative_ext != '')
405      {
406        $insert{'representative_ext'} = $representative_ext;
407      }
408     
409      array_push($inserts, $insert);
410      array_push($insert_links,
411                 array('image_id' => $insert{'id'},
412                       'category_id' => $insert{'storage_category_id'}));
413      array_push($infos, array('path' => $insert{'path'},
414                               'info' => $lang['update_research_added']));
415    }
416  }
417
418  if (count($inserts) > 0)
419  {
420    if (!$simulate)
421    {
422      // inserts all new elements
423      $dbfields = array(
424        'id','file','storage_category_id','date_available','tn_ext'
425        ,'representative_ext','path'
426        );
427      mass_inserts(IMAGES_TABLE, $dbfields, $inserts);
428
429      // insert all links between new elements and their storage category
430      $dbfields = array('image_id','category_id');
431      mass_inserts(IMAGE_CATEGORY_TABLE, $dbfields, $insert_links);
432    }
433    $counts['new_elements'] = count($inserts);
434  }
435
436  // delete elements that are in database but not in the filesystem
437  $to_delete_elements = array();
438  foreach (array_diff($db_elements, $fs['elements']) as $path)
439  {
440    array_push($to_delete_elements, array_search($path, $db_elements));
441    array_push($infos, array('path' => $path,
442                             'info' => $lang['update_research_deleted']));
443  }
444  if (count($to_delete_elements) > 0)
445  {
446    if (!$simulate)
447    {
448      delete_elements($to_delete_elements);
449    }
450    $counts['del_elements'] = count($to_delete_elements);
451  }
452 
453  echo get_elapsed_time($start_files, get_moment());
454  echo ' for new method scanning files<br />';
455}
456// +-----------------------------------------------------------------------+
457// |                        template initialization                        |
458// +-----------------------------------------------------------------------+
459$template->set_filenames(array('update'=>'admin/update.tpl'));
460
461$result_title = '';
462if (isset($simulate) and $simulate)
463{
464  $result_title.= $lang['update_simulation_title'].' ';
465}
466$result_title.= $lang['update_part_research'];
467
468$template->assign_vars(
469  array(
470    'L_SUBMIT'=>$lang['submit'],
471    'L_UPDATE_TITLE'=>$lang['update_default_title'],
472    'L_UPDATE_SYNC_FILES'=>$lang['update_sync_files'],
473    'L_UPDATE_SYNC_DIRS'=>$lang['update_sync_dirs'],
474    'L_UPDATE_SYNC_ALL'=>$lang['update_sync_all'],
475    'L_UPDATE_SYNC_METADATA'=>$lang['update_sync_metadata'],
476    'L_UPDATE_SYNC_METADATA_NEW'=>$lang['update_sync_metadata_new'],
477    'L_UPDATE_SYNC_METADATA_ALL'=>$lang['update_sync_metadata_all'],
478    'L_UPDATE_CATS_SUBSET'=>$lang['update_cats_subset'],
479    'L_RESULT_UPDATE'=>$result_title,
480    'L_NB_NEW_ELEMENTS'=>$lang['update_nb_new_elements'],
481    'L_NB_NEW_CATEGORIES'=>$lang['update_nb_new_categories'],
482    'L_NB_DEL_ELEMENTS'=>$lang['update_nb_del_elements'],
483    'L_NB_DEL_CATEGORIES'=>$lang['update_nb_del_categories'],
484    'L_UPDATE_NB_ERRORS'=>$lang['update_nb_errors'],
485    'L_SEARCH_SUBCATS_INCLUDED'=>$lang['search_subcats_included'],
486    'L_UPDATE_WRONG_DIRNAME_INFO'=>$lang['update_wrong_dirname_info'],
487    'L_UPDATE_MISSING_TN_INFO'=>$lang['update_missing_tn_info'],
488    'PICTURE_EXT_LIST'=>implode(',', $conf['picture_ext']),
489    'L_UPDATE_ERROR_LIST_TITLE'=>$lang['update_error_list_title'],
490    'L_UPDATE_ERRORS_CAPTION'=>$lang['update_errors_caption'],
491    'L_UPDATE_DISPLAY_INFO'=>$lang['update_display_info'],
492    'L_UPDATE_SIMULATE'=>$lang['update_simulate'],
493    'L_UPDATE_INFOS_TITLE'=>$lang['update_infos_title']
494    ));
495// +-----------------------------------------------------------------------+
496// |                        introduction : choices                         |
497// +-----------------------------------------------------------------------+
498if (!isset($_POST['submit']))
499{
500  $template->assign_block_vars('introduction', array());
501
502  $query = '
503SELECT id,name,uppercats,global_rank
504  FROM '.CATEGORIES_TABLE.'
505  WHERE site_id = 1
506;';
507  display_select_cat_wrapper($query,
508                             array(),
509                             'introduction.category_option',
510                             false);
511}
512// +-----------------------------------------------------------------------+
513// |                          synchronize files                            |
514// +-----------------------------------------------------------------------+
515else if (isset($_POST['submit'])
516         and ($_POST['sync'] == 'dirs' or $_POST['sync'] == 'files'))
517{
518  $template->assign_block_vars(
519    'update',
520    array(
521      'NB_NEW_CATEGORIES'=>$counts['new_categories'],
522      'NB_DEL_CATEGORIES'=>$counts['del_categories'],
523      'NB_NEW_ELEMENTS'=>$counts['new_elements'],
524      'NB_DEL_ELEMENTS'=>$counts['del_elements'],
525      'NB_ERRORS'=>count($errors),
526      ));
527 
528  if (count($errors) > 0)
529  {
530    $template->assign_block_vars('update.errors', array());
531    foreach ($errors as $error)
532    {
533      $template->assign_block_vars(
534        'update.errors.error',
535        array(
536          'ELEMENT' => $error['path'],
537          'LABEL' => $error['type'].' ('.$error_labels[$error['type']].')'
538          ));
539    }
540  }
541  if (count($infos) > 0
542      and isset($_POST['display_info'])
543      and $_POST['display_info'] == 1)
544  {
545    $template->assign_block_vars('update.infos', array());
546    foreach ($infos as $info)
547    {
548      $template->assign_block_vars(
549        'update.infos.info',
550        array(
551          'ELEMENT' => $info['path'],
552          'LABEL' => $info['info']
553          ));
554    }
555  }
556
557  if (!$simulate)
558  {
559    $start = get_moment();
560    update_category('all');
561    echo get_elapsed_time($start,get_moment());
562    echo ' for update_category(all)<br />';
563    $start = get_moment();
564    ordering();
565    update_global_rank();
566    echo get_elapsed_time($start, get_moment());
567    echo ' for ordering categories<br />';
568  }
569}
570// +-----------------------------------------------------------------------+
571// |                          synchronize metadata                         |
572// +-----------------------------------------------------------------------+
573else if (isset($_POST['submit']) and preg_match('/^metadata/', $_POST['sync']))
574{
575  // sync only never synchronized files ?
576  if ($_POST['sync'] == 'metadata_new')
577  {
578    $opts['only_new'] = true;
579  }
580  else
581  {
582    $opts['only_new'] = false;
583  }
584  $opts['category_id'] = '';
585  $opts['recursive'] = true;
586 
587  if (isset($_POST['cat']))
588  {
589    $opts['category_id'] = $_POST['cat'];
590    // recursive ?
591    if (!isset($_POST['subcats-included']) or $_POST['subcats-included'] != 1)
592    {
593      $opts['recursive'] = false;
594    }
595  }
596  $start = get_moment();
597  $files = get_filelist($opts['category_id'],
598                        $opts['recursive'],
599                        $opts['only_new']);
600  echo get_elapsed_time($start, get_moment()).' for get_filelist<br />';
601 
602  $start = get_moment();
603  update_metadata($files);
604  echo get_elapsed_time($start, get_moment()).' for metadata update<br />';
605}
606// +-----------------------------------------------------------------------+
607// |                          sending html code                            |
608// +-----------------------------------------------------------------------+
609$template->assign_var_from_handle('ADMIN_CONTENT', 'update');
610?>
Note: See TracBrowser for help on using the repository browser.