array( l10n('wrong filename'), l10n('The name of directories and files must be composed of letters, numbers, "-", "_" or "."') ), 'PWG-UPDATE-2' => array( l10n('missing thumbnail'), l10n('a picture filetype requires a thumbnail. The thumbnail must be present in the sub-directory "thumbnail" of the album directory. The thumbnail filename must start with the configured thumbnail prefix and the extension must be among the following list :').implode(',', $conf['picture_ext']) ), 'PWG-ERROR-NO-FS' => array( l10n('File/directory read error'), l10n('The file or directory cannot be accessed (either it does not exist or the access is denied)') ), 'PWG-ERROR-VERSION' => array( l10n('Piwigo version differs on the remote site'), l10n('Version of create_listing_file.php on the remote site and Piwigo must be the same') ), 'PWG-ERROR-NOLISTING' => array( l10n('listing.xml file was not found'), l10n('listing.xml file was not found on the remote site. This file is generated by choosing the "generate listing" command in the Site manager') ) ); $errors = array(); $infos = array(); if ($site_is_remote) { include_once(PHPWG_ROOT_PATH.'admin/site_reader_remote.php'); $local_listing = null; if ( isset($_GET['local_listing']) and $_GET['local_listing'] ) { $local_listing = PHPWG_ROOT_PATH.'listing.xml'; } $site_reader = new RemoteSiteReader($site_url, $local_listing); } else { include_once( PHPWG_ROOT_PATH.'admin/site_reader_local.php'); $site_reader = new LocalSiteReader($site_url); } $general_failure = true; if (isset($_POST['submit'])) { if (!isset($conf['flip_picture_ext'])) { $conf['flip_picture_ext'] = array_flip($conf['picture_ext']); } if ($site_reader->open()) { $general_failure = false; } // shall we simulate only if (isset($_POST['simulate']) and $_POST['simulate'] == 1) { $simulate = true; } else { $simulate = false; } } // +-----------------------------------------------------------------------+ // | directories / categories | // +-----------------------------------------------------------------------+ if (isset($_POST['submit']) and ($_POST['sync'] == 'dirs' or $_POST['sync'] == 'files')) { $counts['new_categories'] = 0; $counts['del_categories'] = 0; $counts['del_elements'] = 0; $counts['new_elements'] = 0; $counts['upd_elements'] = 0; } if (isset($_POST['submit']) and ($_POST['sync'] == 'dirs' or $_POST['sync'] == 'files') and !$general_failure) { $start = get_moment(); // which categories to update ? $query = ' SELECT id, uppercats, global_rank, status, visible FROM '.CATEGORIES_TABLE.' WHERE dir IS NOT NULL AND site_id = '.$site_id; if (isset($_POST['cat']) and is_numeric($_POST['cat'])) { if (isset($_POST['subcats-included']) and $_POST['subcats-included'] == 1) { $query.= ' AND uppercats '.DB_REGEX_OPERATOR.' \'(^|,)'.$_POST['cat'].'(,|$)\' '; } else { $query.= ' AND id = '.$_POST['cat'].' '; } } $db_categories = hash_from_query($query, 'id'); // get categort full directories in an array for comparison with file // system directory tree $db_fulldirs = get_fulldirs(array_keys($db_categories)); // what is the base directory to search file system sub-directories ? if (isset($_POST['cat']) and is_numeric($_POST['cat'])) { $basedir = $db_fulldirs[$_POST['cat']]; } else { $basedir = preg_replace('#/*$#', '', $site_url); } // we need to have fulldirs as keys to make efficient comparison $db_fulldirs = array_flip($db_fulldirs); // finding next rank for each id_uppercat. By default, each category id // has 1 for next rank on its sub-categories to create $next_rank['NULL'] = 1; $query = ' SELECT id FROM '.CATEGORIES_TABLE; $result = pwg_query($query); while ($row = pwg_db_fetch_assoc($result)) { $next_rank[$row['id']] = 1; } // let's see if some categories already have some sub-categories... $query = ' SELECT id_uppercat, MAX(rank)+1 AS next_rank FROM '.CATEGORIES_TABLE.' GROUP BY id_uppercat'; $result = pwg_query($query); while ($row = pwg_db_fetch_assoc($result)) { // for the id_uppercat NULL, we write 'NULL' and not the empty string if (!isset($row['id_uppercat']) or $row['id_uppercat'] == '') { $row['id_uppercat'] = 'NULL'; } $next_rank[$row['id_uppercat']] = $row['next_rank']; } // next category id available $next_id = pwg_db_nextval('id', CATEGORIES_TABLE); // retrieve sub-directories fulldirs from the site reader $fs_fulldirs = $site_reader->get_full_directories($basedir); // get_full_directories doesn't include the base directory, so if it's a // category directory, we need to include it in our array if (isset($_POST['cat'])) { array_push($fs_fulldirs, $basedir); } // If $_POST['subcats-included'] != 1 ("Search in sub-albums" is unchecked) // $db_fulldirs doesn't include any subdirectories and $fs_fulldirs does // So $fs_fulldirs will be limited to the selected basedir // (if that one is in $fs_fulldirs) if (!isset($_POST['subcats-included']) or $_POST['subcats-included'] != 1) { $fs_fulldirs = array_intersect($fs_fulldirs, array_keys($db_fulldirs)); } $inserts = array(); // new categories are the directories not present yet in the database foreach (array_diff($fs_fulldirs, array_keys($db_fulldirs)) as $fulldir) { $dir = basename($fulldir); if (preg_match('/^[a-zA-Z0-9-_.]+$/', $dir)) { $insert = array( 'id' => $next_id++, 'dir' => $dir, 'name' => str_replace('_', ' ', $dir), 'site_id' => $site_id, 'commentable' => boolean_to_string($conf['newcat_default_commentable']), 'status' => $conf['newcat_default_status'], 'visible' => boolean_to_string($conf['newcat_default_visible']), ); if (isset($db_fulldirs[dirname($fulldir)])) { $parent = $db_fulldirs[dirname($fulldir)]; $insert['id_uppercat'] = $parent; $insert['uppercats'] = $db_categories[$parent]['uppercats'].','.$insert['id']; $insert['rank'] = $next_rank[$parent]++; $insert['global_rank'] = $db_categories[$parent]['global_rank'].'.'.$insert['rank']; if ('private' == $db_categories[$parent]['status']) { $insert['status'] = 'private'; } if ('false' == $db_categories[$parent]['visible']) { $insert['visible'] = 'false'; } } else { $insert['uppercats'] = $insert['id']; $insert{'rank'} = $next_rank['NULL']++; $insert['global_rank'] = $insert['rank']; } array_push($inserts, $insert); array_push( $infos, array( 'path' => $fulldir, 'info' => l10n('added') ) ); // add the new category to $db_categories and $db_fulldirs array $db_categories[$insert{'id'}] = array( 'id' => $insert['id'], 'status' => $insert['status'], 'visible' => $insert['visible'], 'uppercats' => $insert['uppercats'], 'global_rank' => $insert['global_rank'] ); $db_fulldirs[$fulldir] = $insert['id']; $next_rank[$insert{'id'}] = 1; } else { array_push( $errors, array( 'path' => $fulldir, 'type' => 'PWG-UPDATE-1' ) ); } } if (count($inserts) > 0) { if (!$simulate) { $dbfields = array( 'id','dir','name','site_id','id_uppercat','uppercats','commentable', 'visible','status','rank','global_rank' ); mass_inserts(CATEGORIES_TABLE, $dbfields, $inserts); } $counts['new_categories'] = count($inserts); } // to delete categories $to_delete = array(); foreach (array_diff(array_keys($db_fulldirs), $fs_fulldirs) as $fulldir) { array_push($to_delete, $db_fulldirs[$fulldir]); unset($db_fulldirs[$fulldir]); array_push($infos, array('path' => $fulldir, 'info' => l10n('deleted'))); } if (count($to_delete) > 0) { if (!$simulate) { delete_categories($to_delete); } $counts['del_categories'] = count($to_delete); } $template->append('footer_elements', '' ); } // +-----------------------------------------------------------------------+ // | files / elements | // +-----------------------------------------------------------------------+ if (isset($_POST['submit']) and $_POST['sync'] == 'files' and !$general_failure) { $start_files = get_moment(); $start= $start_files; $fs = $site_reader->get_elements($basedir); $template->append('footer_elements', '' ); $cat_ids = array_diff(array_keys($db_categories), $to_delete); $db_elements = array(); if (count($cat_ids) > 0) { $query = ' SELECT id, path FROM '.IMAGES_TABLE.' WHERE storage_category_id IN (' .wordwrap( implode(', ', $cat_ids), 80, "\n" ).')'; $db_elements = simple_hash_from_query($query, 'id', 'path'); } // next element id available $next_element_id = pwg_db_nextval('id', IMAGES_TABLE); $start = get_moment(); $inserts = array(); $insert_links = array(); foreach (array_diff(array_keys($fs), $db_elements) as $path) { $insert = array(); // storage category must exist $dirname = dirname($path); if (!isset($db_fulldirs[$dirname])) { continue; } $filename = basename($path); if (!preg_match('/^[a-zA-Z0-9-_.]+$/', $filename)) { array_push( $errors, array( 'path' => $path, 'type' => 'PWG-UPDATE-1' ) ); continue; } if ( isset( $conf['flip_picture_ext'][get_extension($filename)] ) and !isset($fs[$path]['tn_ext']) ) { // For a picture thumbnail is mandatory and for non picture element, // thumbnail and representative are optionnal array_push( $errors, array( 'path' => $path, 'type' => 'PWG-UPDATE-2' ) ); } else { $insert = array( 'id' => $next_element_id++, 'file' => $filename, 'date_available' => CURRENT_DATE, 'path' => $path, 'tn_ext' => isset($fs[$path]['tn_ext']) ? $fs[$path]['tn_ext'] : null, 'storage_category_id' => $db_fulldirs[$dirname], 'added_by' => $user['id'], ); if ( $_POST['privacy_level']!=0 ) { $insert['level'] = $_POST['privacy_level']; } array_push( $inserts, $insert ); array_push( $insert_links, array( 'image_id' => $insert['id'], 'category_id' => $insert['storage_category_id'], ) ); array_push( $infos, array( 'path' => $insert['path'], 'info' => l10n('added') ) ); $caddiables[] = $insert['id']; } } if (count($inserts) > 0) { if (!$simulate) { // inserts all new elements mass_inserts( IMAGES_TABLE, array_keys($inserts[0]), $inserts ); // inserts all links between new elements and their storage category mass_inserts( IMAGE_CATEGORY_TABLE, array_keys($insert_links[0]), $insert_links ); // add new photos to caddie if (isset($_POST['add_to_caddie']) and $_POST['add_to_caddie'] == 1) { fill_caddie($caddiables); } } $counts['new_elements'] = count($inserts); } // delete elements that are in database but not in the filesystem $to_delete_elements = array(); foreach (array_diff($db_elements, array_keys($fs)) as $path) { array_push($to_delete_elements, array_search($path, $db_elements)); array_push($infos, array('path' => $path, 'info' => l10n('deleted'))); } if (count($to_delete_elements) > 0) { if (!$simulate) { delete_elements($to_delete_elements); } $counts['del_elements'] = count($to_delete_elements); } $template->append('footer_elements', '' ); } // +-----------------------------------------------------------------------+ // | synchronize files | // +-----------------------------------------------------------------------+ if (isset($_POST['submit']) and ($_POST['sync'] == 'dirs' or $_POST['sync'] == 'files') and !$general_failure ) { if (!$simulate) { $start = get_moment(); update_category('all'); $template->append('footer_elements', '' ); $start = get_moment(); update_global_rank(); $template->append('footer_elements', ''); } if ($_POST['sync'] == 'files') { $start = get_moment(); $opts['category_id'] = ''; $opts['recursive'] = true; if (isset($_POST['cat'])) { $opts['category_id'] = $_POST['cat']; if (!isset($_POST['subcats-included']) or $_POST['subcats-included'] != 1) { $opts['recursive'] = false; } } $files = get_filelist($opts['category_id'], $site_id, $opts['recursive'], false); $template->append('footer_elements', ''); $start = get_moment(); $datas = array(); foreach ( $files as $id=>$file ) { $data = $site_reader->get_element_update_attributes($file); if ( !is_array($data) ) { continue; } $extension = get_extension($file); if ( isset($conf['flip_picture_ext'][$extension]) ) { if ( !isset($data['tn_ext']) ) { array_push( $errors, array( 'path' => $file, 'type' => 'PWG-UPDATE-2' ) ); continue; } } $data['id']=$id; array_push($datas, $data); } // end foreach file $counts['upd_elements'] = count($datas); if (!$simulate and count($datas)>0 ) { mass_updates( IMAGES_TABLE, // fields array( 'primary' => array('id'), 'update' => $site_reader->get_update_attributes(), ), $datas ); } $template->append('footer_elements', ''); }// end if sync files } // +-----------------------------------------------------------------------+ // | synchronize files | // +-----------------------------------------------------------------------+ if (isset($_POST['submit']) and ($_POST['sync'] == 'dirs' or $_POST['sync'] == 'files')) { $template->assign( 'update_result', array( 'NB_NEW_CATEGORIES'=>$counts['new_categories'], 'NB_DEL_CATEGORIES'=>$counts['del_categories'], 'NB_NEW_ELEMENTS'=>$counts['new_elements'], 'NB_DEL_ELEMENTS'=>$counts['del_elements'], 'NB_UPD_ELEMENTS'=>$counts['upd_elements'], 'NB_ERRORS'=>count($errors), )); } // +-----------------------------------------------------------------------+ // | synchronize metadata | // +-----------------------------------------------------------------------+ if (isset($_POST['submit']) and isset($_POST['sync_meta']) and !$general_failure) { // sync only never synchronized files ? $opts['only_new'] = isset($_POST['meta_all']) ? false : true; $opts['category_id'] = ''; $opts['recursive'] = true; if (isset($_POST['cat'])) { $opts['category_id'] = $_POST['cat']; // recursive ? if (!isset($_POST['subcats-included']) or $_POST['subcats-included'] != 1) { $opts['recursive'] = false; } } $start = get_moment(); $files = get_filelist($opts['category_id'], $site_id, $opts['recursive'], $opts['only_new']); $template->append('footer_elements', ''); $start = get_moment(); $datas = array(); $tags_of = array(); $has_high_images = array(); $image_ids = array(); foreach ($files as $id => $file) { array_push($image_ids, $id); } if (count($image_ids) > 0) { $query = ' SELECT id FROM '.IMAGES_TABLE.' WHERE has_high = \'true\' AND id IN ( '.wordwrap(implode(', ', $image_ids), 80, "\n").' )'; $has_high_images = array_from_query($query, 'id' ); } foreach ( $files as $id=>$file ) { $data = $site_reader->get_element_metadata( $file, in_array($id, $has_high_images) ); if ( is_array($data) ) { $data['date_metadata_update'] = CURRENT_DATE; $data['id']=$id; array_push($datas, $data); foreach (array('keywords', 'tags') as $key) { if (isset($data[$key])) { if (!isset($tags_of[$id])) { $tags_of[$id] = array(); } foreach (explode(',', $data[$key]) as $tag_name) { array_push( $tags_of[$id], tag_id_from_tag_name($tag_name) ); } } } } else { array_push($errors, array('path' => $file, 'type' => 'PWG-ERROR-NO-FS')); } } if (!$simulate) { if (count($datas) > 0) { mass_updates( IMAGES_TABLE, // fields array( 'primary' => array('id'), 'update' => array_unique( array_merge( array_diff( $site_reader->get_metadata_attributes(), // keywords and tags fields are managed separately array('keywords', 'tags') ), array('date_metadata_update')) ) ), $datas, isset($_POST['meta_empty_overrides']) ? 0 : MASS_UPDATES_SKIP_EMPTY ); } set_tags_of($tags_of); } $template->append('footer_elements', ''); $template->assign( 'metadata_result', array( 'NB_ELEMENTS_DONE' => count($datas), 'NB_ELEMENTS_CANDIDATES' => count($files), 'NB_ERRORS' => count($errors), )); } // +-----------------------------------------------------------------------+ // | template initialization | // +-----------------------------------------------------------------------+ $template->set_filenames(array('update'=>'site_update.tpl')); $result_title = ''; if (isset($simulate) and $simulate) { $result_title.= l10n('[Simulation]').' '; } // used_metadata string is displayed to inform admin which metadata will be // used from files for synchronization $used_metadata = implode( ', ', $site_reader->get_metadata_attributes()); if ($site_is_remote and !isset($_POST['submit']) ) { $used_metadata.= ' + ...'; } $template->assign( array( 'SITE_URL'=>$site_url, 'U_SITE_MANAGER'=> get_root_url().'admin.php?page=site_manager', 'L_RESULT_UPDATE'=>$result_title.l10n('Search for new images in the directories'), 'L_RESULT_METADATA'=>$result_title.l10n('Metadata synchronization results'), 'METADATA_LIST' => $used_metadata, 'U_HELP' => get_root_url().'admin/popuphelp.php?page=synchronize', )); // +-----------------------------------------------------------------------+ // | introduction : choices | // +-----------------------------------------------------------------------+ if (isset($_POST['submit'])) { $tpl_introduction = array( 'sync' => $_POST['sync'], 'sync_meta' => isset($_POST['sync_meta']) ? true : false, 'display_info' => isset($_POST['display_info']) and $_POST['display_info']==1, 'add_to_caddie' => isset($_POST['add_to_caddie']) and $_POST['add_to_caddie']==1, 'subcats_included' => isset($_POST['subcats-included']) and $_POST['subcats-included']==1, 'privacy_level_selected' => (int)@$_POST['privacy_level'], 'meta_all' => isset($_POST['meta_all']) ? true : false, 'meta_empty_overrides' => isset($_POST['meta_empty_overrides']) ? true : false, ); if (isset($_POST['cat']) and is_numeric($_POST['cat'])) { $cat_selected = array($_POST['cat']); } else { $cat_selected = array(); } } else { $tpl_introduction = array( 'sync' => 'dirs', 'sync_meta' => true, 'display_info' => false, 'add_to_caddie' => false, 'subcats_included' => true, 'privacy_level_selected' => 0, 'meta_all' => false, 'meta_empty_overrides' => false, ); $cat_selected = array(); if (isset($_GET['cat_id'])) { check_input_parameter('cat_id', $_GET, false, PATTERN_ID); $cat_selected = array($_GET['cat_id']); $tpl_introduction['sync'] = 'files'; } } $tpl_introduction['privacy_level_options'] = get_privacy_level_options(); $template->assign('introduction', $tpl_introduction); $query = ' SELECT id,name,uppercats,global_rank FROM '.CATEGORIES_TABLE.' WHERE site_id = '.$site_id; display_select_cat_wrapper($query, $cat_selected, 'category_options', false); if (count($errors) > 0) { foreach ($errors as $error) { $template->append( 'sync_errors', array( 'ELEMENT' => $error['path'], 'LABEL' => $error['type'].' ('.$error_labels[$error['type']][0].')' )); } foreach ($error_labels as $error_type=>$error_description) { $template->append( 'sync_error_captions', array( 'TYPE' => $error_type, 'LABEL' => $error_description[1] )); } } if (count($infos) > 0 and isset($_POST['display_info']) and $_POST['display_info'] == 1) { foreach ($infos as $info) { $template->append( 'sync_infos', array( 'ELEMENT' => $info['path'], 'LABEL' => $info['info'] )); } } // +-----------------------------------------------------------------------+ // | sending html code | // +-----------------------------------------------------------------------+ $template->assign_var_from_handle('ADMIN_CONTENT', 'update'); ?>