Changeset 19446


Ignore:
Timestamp:
Dec 16, 2012, 3:21:10 PM (8 years ago)
Author:
mistic100
Message:
  • add regex for phot name, author
  • add dimensions filter
  • rewrite javascript algorithms
  • add auto update on timeout (default 3 days)
  • display photos count on plugin albums list
Location:
extensions/SmartAlbums
Files:
1 added
13 edited

Legend:

Unmodified
Added
Removed
  • extensions/SmartAlbums/admin/album.php

    r17677 r19446  
    7272if (isset($_POST['submitFilters']))
    7373{
     74  if (defined('SMART_DEBUG'))
     75  {
     76    var_dump($_POST['filters']);
     77  }
     78 
    7479  // test if it was a Smart Album
    7580  $query = '
     
    98103    pwg_query('DELETE FROM '.CATEGORY_FILTERS_TABLE.' WHERE category_id = '.$cat_id.';');
    99104   
     105    $inserts = array();
    100106    foreach ($_POST['filters'] as $filter)
    101107    {
    102108      if (($filter = smart_check_filter($filter)) != false)
    103109      {
    104         $query = '
    105 INSERT IGNORE INTO '.CATEGORY_FILTERS_TABLE.'
    106   VALUES(
    107     '.$cat_id.',
    108     "'.$filter['type'].'",
    109     "'.$filter['cond'].'",
    110     "'.$filter['value'].'"
    111   )
    112 ;';
    113       pwg_query($query);
     110        $filter['category_id'] = $cat_id;
     111        $inserts[] = $filter;
    114112      }
    115113    }
     114   
     115    mass_inserts(
     116      CATEGORY_FILTERS_TABLE,
     117      array('category_id', 'type', 'cond', 'value'),
     118      $inserts,
     119      array('ignore'=>true)
     120      );
    116121   
    117122    $associated_images = smart_make_associations($cat_id);
     
    143148    'name' => l10n('Date'),
    144149    'options' => array(
    145       'the_post'      => l10n('Added on'),
    146       'before_post'   => l10n('Added before'),
    147       'after_post'    => l10n('Added after'),
    148       'the_taken'     => l10n('Created on'),
    149       'before_taken'  => l10n('Created before'),
    150       'after_taken'   => l10n('Created after'),
     150      'the_post'     => l10n('Added on'),
     151      'before_post'  => l10n('Added before'),
     152      'after_post'   => l10n('Added after'),
     153      'the_taken'    => l10n('Created on'),
     154      'before_taken' => l10n('Created before'),
     155      'after_taken'  => l10n('Created after'),
    151156      ),
    152157    ),
     
    160165      'not_begin'   => l10n('Doesn\'t begin with'),
    161166      'not_end'     => l10n('Doesn\'t end with'),
     167      'regex'       => l10n('Regular expression'),
    162168      ),
    163169    ),
     
    171177      ),
    172178    ),
     179  'dimensions' => array(
     180    'name' => l10n('Dimensions'),
     181    'options' => array(
     182      'width'  => l10n('Width'),
     183      'height' => l10n('Height'),
     184      'ratio'  => l10n('Ratio').' ('.l10n('Width').'/'.l10n('Height').')',
     185      ),
     186    ),
    173187  'author' => array(
    174188    'name' => l10n('Author'),
     
    178192      'not_is'  => l10n('Is not'),
    179193      'not_in'  => l10n('Is not in'),
     194      'regex'   => l10n('Regular expression'),
    180195      ),
    181196    ),
     
    205220$template->assign('options', $options);
    206221
     222
    207223/* get filters for this album */
    208224$query = '
    209225SELECT *
    210226  FROM '.CATEGORY_FILTERS_TABLE.'
    211   WHERE category_id = '.$cat_id.' 
     227  WHERE category_id = '.$cat_id.'
    212228  ORDER BY
    213229    type ASC,
     
    216232$result = pwg_query($query);
    217233
     234$template->assign('filter_mode', 'and');
     235
    218236while ($filter = pwg_db_fetch_assoc($result))
    219237{
    220   // get tags name and id
    221   if ($filter['type'] == 'tags')
     238  if ($filter['type'] == 'mode')
     239  {
     240    $template->assign('filter_mode', $filter['value']);
     241    continue;
     242  }
     243  else if ($filter['type'] == 'tags')
    222244  {
    223245    $query = '
    224 SELECT
    225     id,
    226     name
     246SELECT id, name
    227247  FROM '.TAGS_TABLE.'
    228248  WHERE id IN('.$filter['value'].')
     
    230250    $filter['value'] = get_taglist($query);
    231251  }
    232   else if ($filter['type'] == 'album')
    233   {
    234     $filter['value'] = explode(',', $filter['value']);
    235   }
    236252 
    237   $template->append('filters', array(
    238     'TYPE' => $filter['type'],
    239     'COND' => $filter['cond'],
    240     'VALUE' => $filter['value'],
    241     'CAPTION' => $options[ $filter['type'] ]['name'],
     253  $template->append('filters', $filter);
     254}
     255
     256
     257/* format types */
     258$template->assign('format_options', array(
     259  'portrait' => l10n('Portrait'),
     260  'square'   => l10n('Square'),
     261  'lanscape' => l10n('Landscape'),
     262  'panorama' => l10n('Panorama'),
    242263  ));
    243 }
    244264
    245265/* all tags */
    246266$query = '
    247 SELECT
    248     id,
    249     name
     267SELECT id, name
    250268  FROM '.TAGS_TABLE.'
    251269;';
     
    262280;';
    263281display_select_cat_wrapper($query, array(), 'all_albums');
     282
     283// +-----------------------------------------------------------------------+
     284// |                              dimensions                               |
     285// +-----------------------------------------------------------------------+
     286
     287$widths = array();
     288$heights = array();
     289$ratios = array();
     290
     291// get all width, height and ratios
     292$query = '
     293SELECT
     294  DISTINCT width, height
     295  FROM '.IMAGES_TABLE.'
     296  WHERE width IS NOT NULL
     297    AND height IS NOT NULL
     298;';
     299$result = pwg_query($query);
     300
     301while ($row = pwg_db_fetch_assoc($result))
     302{
     303  $widths[] = $row['width'];
     304  $heights[] = $row['height'];
     305  $ratios[] = floor($row['width'] * 100 / $row['height']) / 100;
     306}
     307
     308$widths = array_unique($widths);
     309sort($widths);
     310
     311$heights = array_unique($heights);
     312sort($heights);
     313
     314$ratios = array_unique($ratios);
     315sort($ratios);
     316
     317$dimensions['bounds'] = array(
     318  'min_width' => $widths[0],
     319  'max_width' => $widths[count($widths)-1],
     320  'min_height' => $heights[0],
     321  'max_height' => $heights[count($heights)-1],
     322  'min_ratio' => $ratios[0],
     323  'max_ratio' => $ratios[count($ratios)-1],
     324  );
     325
     326// find ratio categories
     327$ratio_categories = array(
     328  'portrait' => array(),
     329  'square' => array(),
     330  'landscape' => array(),
     331  'panorama' => array(),
     332  );
     333
     334foreach ($ratios as $ratio)
     335{
     336  if ($ratio < 0.95)
     337  {
     338    $ratio_categories['portrait'][] = $ratio;
     339  }
     340  else if ($ratio >= 0.95 and $ratio <= 1.05)
     341  {
     342    $ratio_categories['square'][] = $ratio;
     343  }
     344  else if ($ratio > 1.05 and $ratio < 2)
     345  {
     346    $ratio_categories['landscape'][] = $ratio;
     347  }
     348  else if ($ratio >= 2)
     349  {
     350    $ratio_categories['panorama'][] = $ratio;
     351  }
     352}
     353
     354foreach (array_keys($ratio_categories) as $ratio_category)
     355{
     356  if (count($ratio_categories[$ratio_category]) > 0)
     357  {
     358    $dimensions['ratio_'.$ratio_category] = array(
     359      'min' => $ratio_categories[$ratio_category][0],
     360      'max' => $ratio_categories[$ratio_category][count($ratio_categories[$ratio_category]) - 1]
     361      );
     362  }
     363}
     364
     365$template->assign('dimensions', $dimensions);
    264366
    265367/* get image number */
     
    289391  'level_options' => get_privacy_level_options(),
    290392  'F_ACTION' => $self_url,
    291   'CATEGORIES_NAV' => get_cat_display_name_cache(
    292     $category['uppercats'],
    293     SMART_ADMIN.'-album&amp;cat_id='
    294     ),
     393  'CATEGORIES_NAV' => get_cat_display_name_cache($category['uppercats'], SMART_ADMIN.'-album&amp;cat_id='),
    295394));
    296395
  • extensions/SmartAlbums/admin/cat_list.php

    r16104 r19446  
    2121    permalink,
    2222    dir,
    23     rank,
    24     status
     23    smart_update
    2524  FROM '.CATEGORIES_TABLE.' AS cat
    2625  INNER JOIN '.CATEGORY_FILTERS_TABLE.' AS cf
     
    124123// +-----------------------------------------------------------------------+
    125124
    126 // get the categories containing images directly
    127 $categories_with_images = array();
     125$categories_count_images = array();
    128126if ( count($categories) )
    129127{
    130128  $query = '
    131 SELECT DISTINCT category_id
     129SELECT
     130    category_id,
     131    COUNT(image_id) AS total_images
    132132  FROM '.IMAGE_CATEGORY_TABLE.'
    133   WHERE category_id IN ('.implode(',', array_keys($categories)).')';
    134   $categories_with_images = array_flip( array_from_query($query, 'category_id') );
     133  WHERE category_id IN ('.implode(',', array_keys($categories)).')
     134  GROUP BY category_id
     135;';
     136  $categories_count_images = simple_hash_from_query($query, 'category_id', 'total_images');
    135137}
    136138
     
    141143  $tpl_cat =
    142144    array(
    143       'NAME'       => get_cat_display_name_from_id($category['id'], $base_url.'album-'),
    144       'ID'         => $category['id'],
    145       'RANK'       => $category['rank']*10,
     145      'NAME'        => get_cat_display_name_from_id($category['id'], $base_url.'album-'),
     146      'ID'          => $category['id'],
     147      'IMG_COUNT'   => !empty($categories_count_images[ $category['id'] ]) ? $categories_count_images[ $category['id'] ] : 0,
     148      'LAST_UPDATE' => format_date($category['smart_update'], true),
    146149
    147       'U_JUMPTO'   => make_index_url(
    148         array(
    149           'category' => $category
    150           )
    151         ),
    152 
    153       'U_EDIT'     => $base_url.'album-'.$category['id'],
    154       'U_DELETE'   => $self_url.'&amp;delete='.$category['id'].'&amp;pwg_token='.get_pwg_token(),
    155       'U_SMART'    => $self_url.'&amp;smart_generate='.$category['id'],
     150      'U_JUMPTO'    => make_index_url(array('category' => $category)),
     151      'U_EDIT'      => SMART_ADMIN.'-album&amp;cat_id='.$category['id'],
     152      'U_DELETE'    => $self_url.'&amp;delete='.$category['id'].'&amp;pwg_token='.get_pwg_token(),
     153      'U_SMART'     => $self_url.'&amp;smart_generate='.$category['id'],
    156154    );
    157 
    158   if ( array_key_exists($category['id'], $categories_with_images) )
    159   {
    160     $tpl_cat['U_MANAGE_ELEMENTS'] =
    161       $base_url.'batch_manager&amp;cat='.$category['id'];
    162   }
    163155 
    164156  $template->append('categories', $tpl_cat);
  • extensions/SmartAlbums/admin/config.php

    r16939 r19446  
    55if (isset($_POST['submit']))
    66{
    7   $conf['SmartAlbums']['update_on_upload'] = isset($_POST['update_on_upload']);
    8   $conf['SmartAlbums']['smart_is_forbidden'] = isset($_POST['smart_is_forbidden']);
     7  if ( $_POST['update_timeout'] == 0 or !preg_match('#^[0-9.]+$#', $_POST['update_timeout']) )
     8  {
     9    array_push($page['errors'], l10n('Invalid number of days'));
     10    $_POST['update_timeout'] = $conf['SmartAlbums']['update_timeout'];
     11  }
     12   
     13  $conf['SmartAlbums'] = array(
     14    'show_list_messages' => $conf['SmartAlbums']['show_list_messages'],
     15    'last_update' =>        $conf['SmartAlbums']['last_update'],
     16    'update_on_upload' =>   isset($_POST['update_on_upload']),
     17    'update_on_date' =>     isset($_POST['update_on_date']),
     18    'update_timeout' =>     $_POST['update_timeout'],
     19    'smart_is_forbidden' => isset($_POST['smart_is_forbidden']),
     20    );
    921 
    1022  conf_update_param('SmartAlbums', serialize($conf['SmartAlbums']));
  • extensions/SmartAlbums/admin/template/album.tpl

    r17677 r19446  
    11{combine_css path=$SMART_PATH|@cat:"admin/template/style.css"}
    2 
     2{combine_script id='sprintf' load='footer' path=$SMART_PATH|@cat:"admin/template/sprintf.js"}
    33{include file='include/datepicker.inc.tpl'}
    4 {combine_script id='jquery.tokeninput' load='async' require='jquery' path='themes/default/js/plugins/jquery.tokeninput.js'}
    5 
     4{combine_script id='jquery.tokeninput' load='footer' require='jquery' path='themes/default/js/plugins/jquery.tokeninput.js'}
    65{combine_css path="themes/default/js/plugins/chosen.css"}
    76{combine_script id='jquery.chosen' load='footer' path='themes/default/js/plugins/chosen.jquery.min.js'}
    8 
    9 {footer_script require='jquery.tokeninput,jquery.chosen'}
    10 var lang = new Array();
    11 var options = new Array();
    12 
    13 {foreach from=$options item=details key=mode}
    14   lang['{$mode}_filter'] = '{$details.name|escape:javascript}';
    15   {capture assign="option_content"}{html_options options=$details.options}{/capture}
    16   options['{$mode}'] = "{$option_content|escape:javascript}";
    17 {/foreach}
    18 
    19 lang['Select albums...'] = '{'Select albums...'|@translate}';
    20 lang['For "Is (not) in", separate each author by a comma'] = '{'For "Is (not) in", separate each author by a comma'|@translate|escape:javascript}';
    21 lang['remove this filter'] = '{'remove this filter'|@translate|escape:javascript}';
    22 {capture assign="option_content"}{html_options options=$level_options selected=0}{/capture}
    23 options['level_options'] = "{$option_content|escape:javascript}";
    24 {capture assign="option_content"}{html_options options=$all_albums selected=0}{/capture}
    25 options['album_options'] = "{$option_content|escape:javascript}";
    26 
    27 {literal}
     7{combine_css path="themes/default/js/ui/theme/jquery.ui.slider.css"}
     8{combine_script id='jquery.ui.slider' require='jquery.ui' load='footer' path='themes/default/js/ui/minified/jquery.ui.slider.min.js'}
     9
     10{footer_script}{literal}
     11var count=0;
     12var limit_count=0;
     13var level_count=0;
     14
     15// MAIN EVENT HANDLERS
    2816$('#addFilter').change(function() {
    2917  add_filter($(this).attr('value'));
     
    3220 
    3321$('#removeFilters').click(function() {
    34   $('#filterList li').each(function() {
     22  $('#filtersList li').each(function() {
    3523    $(this).remove();
    3624  });
     25 
     26  limit_level=0;
     27  level_count=0;
    3728  return false;
    3829});
     
    5041
    5142
    52 function add_filter(type) {
    53   // add line
    54   $('<li class="filter_'+ type +'" id="filter_'+ i +'"></li>').appendTo('#filterList');
    55  
    56   //set content
    57   content =
    58     ' <span class="filter-title">'+
    59       ' <a href="#" class="removeFilter" title="'+ lang['remove this filter'] +'"><span>[x]</span></a>'+
    60       ' <input type="hidden" name="filters['+ i +'][type]" value="'+ type +'"/>&nbsp;'+ lang[type +'_filter'] +
    61     '</span>'+
    62     ' <span class="filter-cond">'+
    63       ' <select name="filters['+ i +'][cond]">'+ options[type] +'</select>'+
    64     '</span>'+
    65     ' <span class="filter-value">';
    66  
    67   if (type == 'tags') {
    68     content+= ' <select name="filters['+ i +'][value]" class="tagSelect"></select>';
    69   }
    70   else if (type == 'album') {
    71     content+= ' <select name="filters['+ i +'][value][]" class="albumSelect" multiple="multiple" data-placeholder="'+ lang['Select albums...'] +'">'+ options['album_options'] +'</select>';
     43// ADD FILTER FUNCTIONS
     44function add_filter(type, cond, value) {
     45  count++;
     46 
     47  content = $("#filtersRepo #filter_"+type).html().replace(/iiii/g, count);
     48  $block = $(content);
     49  $("#filtersList").append($block);
     50 
     51  if (cond) {
     52    select_cond($block, type, cond);
     53  }
     54 
     55  if (value) {
     56    if (type == "tags") {
     57      $block.find(".filter-value .tagSelect").html(value);
     58    }
     59    else if (type == "album") {
     60      select_options($block, value);
     61    }
     62    else if (type == "level") {
     63      select_options($block, value);
     64    }
     65    else if (type != "dimensions") {
     66      $block.find(".filter-value input").val(value);
     67    }
     68  }
     69 
     70  init_jquery_handlers($block);
     71 
     72  if (type == "dimensions") {
     73    select_dimensions($block, cond, value);
     74  }
     75 
     76  if (type == 'limit') {
     77    limit_count=1;
     78    $("#addFilter option[value='limit']").attr('disabled','disabled');
    7279  }
    7380  else if (type == 'level') {
    74     content+= ' <select name="filters['+ i +'][value]">'+ options['level_options'] +'</select>';
     81    level_count=1;
     82    $("#addFilter option[value='level']").attr('disabled','disabled');
     83  }
     84}
     85
     86function select_cond($block, type, cond) {
     87  $block.find(".filter-cond option").removeAttr('selected');
     88  $block.find(".filter-cond option[value='"+cond+"']").attr('selected', 'selected');
     89}
     90
     91function select_dimensions($block, cond, value) {
     92  if (!cond) cond = 'width';
     93 
     94  $block.find(".filter-value span:not(.filter_dimension_info)").hide();
     95  $block.find(".filter-value .dimension_"+cond).show();
     96 
     97  if (value) {
     98    values = value.split(',');
    7599  }
    76100  else {
    77     content+= ' <input type="text" name="filters['+ i +'][value]" size="30"/>';
    78   }
    79  
    80   if (type == 'author') {
    81     content+= ' <i>'+ lang['For "Is (not) in", separate each author by a comma'] +'</i>';
    82   }
    83    
    84   content+= '</span>';
    85  
    86   $('#filter_'+ i).html(content);
    87  
    88   // reinit handlers
    89   init_jquery_handlers();
    90   i++;
    91 }
    92 
    93 function init_jquery_handlers() { 
    94   $('.removeFilter').click(function() {
     101    values = $block.find(".filter_dimension_"+cond+"_slider").slider("values");
     102  }
     103  $block.find(".filter_dimension_"+cond+"_slider").slider("values", values);
     104}
     105
     106function select_options($block, value) { 
     107  values = value.split(',');
     108  for (j in values) {
     109    $block.find(".filter-value option[value='"+ values[j] +"']").attr('selected', 'selected');
     110  }
     111}
     112
     113
     114// DECLARE JQUERY PLUGINS AND VERSATILE HANDLERS
     115function init_jquery_handlers($block) {
     116  // remove filter
     117  $block.find(".removeFilter").click(function() {
     118    type = $(this).next("input").val();
     119    if (type == 'limit') {
     120      limit_count=1;
     121      $("#addFilter option[value='limit']").removeAttr('disabled');
     122    }
     123    else if (type == 'level') {
     124      level_count=1;
     125      $("#addFilter option[value='level']").removeAttr('disabled');
     126    }
     127   
    95128    $(this).parents('li').remove();
    96129    return false;
    97130  });
    98131
    99   $('.filter_date input[type="text"]').each(function() {
    100     $(this).datepicker({dateFormat:'yy-mm-dd', firstDay:1});
    101   });
    102  
    103   jQuery(".tagSelect").tokenInput(
    104   {/literal}
    105     [{foreach from=$all_tags item=tag name=tags}{ldelim}"name":"{$tag.name|@escape:'javascript'}","id":"{$tag.id}"{rdelim}{if !$smarty.foreach.tags.last},{/if}{/foreach}],
    106     {ldelim}
    107       hintText: '{'Type in a search term'|@translate}',
    108       noResultsText: '{'No results'|@translate}',
    109       searchingText: '{'Searching...'|@translate}',
    110       animateDropdown: false,
    111       preventDuplicates: true,
    112       allowCreation: false
    113   {literal}
    114     }
    115   );
    116  
    117   jQuery(".albumSelect").chosen();
     132  // date filter
     133  if ($block.hasClass('filter_date')) {
     134    $block.find("input[type='text']").each(function() {
     135      $(this).datepicker({dateFormat:'yy-mm-dd', firstDay:1});
     136    });
     137  }
     138
     139  // tags filter
     140  if ($block.hasClass('filter_tags')) {
     141    $block.find(".tagSelect").tokenInput(
     142    {/literal}
     143      [{foreach from=$all_tags item=tag name=tags}{ldelim}"name":"{$tag.name|@escape:'javascript'}","id":"{$tag.id}"{rdelim}{if !$smarty.foreach.tags.last},{/if}{/foreach}],
     144      {ldelim}
     145        hintText: '{'Type in a search term'|@translate}',
     146        noResultsText: '{'No results'|@translate}',
     147        searchingText: '{'Searching...'|@translate}',
     148        animateDropdown: false,
     149        preventDuplicates: true,
     150        allowCreation: false
     151    {literal}
     152    });
     153  }
     154 
     155  // album filter
     156  if ($block.hasClass('filter_album')) {
     157    $block.find(".albumSelect").chosen();
     158  }
     159 
     160  // dimension filter
     161  if ($block.hasClass('filter_dimensions')) {
     162    $block.find(".filter-cond select").change(function() {
     163      select_dimensions($block, $(this).attr("value"));
     164    });
     165    {/literal}
     166   
     167    $block.find(".filter_dimension_width_slider").slider({ldelim}
     168      range: true,
     169      min: {$dimensions.bounds.min_width},
     170      max: {$dimensions.bounds.max_width},
     171      values: [{$dimensions.bounds.min_width}, {$dimensions.bounds.max_width}],
     172      slide: function(event, ui) {ldelim}
     173        change_dimension_info($block, ui.values, "{'between %d and %d pixels'|@translate}");
     174      },
     175      change: function(event, ui) {ldelim}
     176        change_dimension_info($block, ui.values, "{'between %d and %d pixels'|@translate}");
     177      }
     178    });
     179   
     180    $block.find(".filter_dimension_height_slider").slider({ldelim}
     181      range: true,
     182      min: {$dimensions.bounds.min_height},
     183      max: {$dimensions.bounds.max_height},
     184      values: [{$dimensions.bounds.min_height}, {$dimensions.bounds.max_height}],
     185      slide: function(event, ui) {ldelim}
     186        change_dimension_info($block, ui.values, "{'between %d and %d pixels'|@translate}");
     187      },
     188      change: function(event, ui) {ldelim}
     189        change_dimension_info($block, ui.values, "{'between %d and %d pixels'|@translate}");
     190      }
     191    });
     192   
     193    $block.find(".filter_dimension_ratio_slider").slider({ldelim}
     194      range: true,
     195      step: 0.01,
     196      min: {$dimensions.bounds.min_ratio},
     197      max: {$dimensions.bounds.max_ratio},
     198      values: [{$dimensions.bounds.min_ratio}, {$dimensions.bounds.max_ratio}],
     199      slide: function(event, ui) {ldelim}
     200        change_dimension_info($block, ui.values, "{'between %.2f and %.2f'|@translate}");
     201      },
     202      change: function(event, ui) {ldelim}
     203        change_dimension_info($block, ui.values, "{'between %.2f and %.2f'|@translate}");
     204      }
     205    });
     206    {literal}
     207   
     208    $block.find("a.dimensions-choice").click(function() {
     209      $block.find(".filter_dimension_"+ $(this).data("type") +"_slider").slider("values",
     210        [$(this).data("min"), $(this).data("max")]
     211      );
     212    });
     213  }
     214}
     215
     216
     217// GENERAL FUNCTIONS
     218function change_dimension_info($block, values, text) {
     219  $block.find("input[name$='[value][min]']").val(values[0]);
     220  $block.find("input[name$='[value][max]']").val(values[1]);
     221  $block.find(".filter_dimension_info").html(sprintf(text, values[0], values[1]));
    118222}
    119223
     
    136240  }
    137241}
    138  
    139 init_jquery_handlers();
    140242{/literal}
     243
    141244{if isset($new_smart)}doBlink('.new_smart', 0, 3);{/if}
    142245{/footer_script}
     246
    143247
    144248<div class="titrePage">
     
    153257    <legend>{'Filters'|@translate}</legend>
    154258     
    155     <ul id="filterList">
    156       {counter start=0 assign=i}
    157       {foreach from=$filters item=filter}
    158         <li class="filter_{$filter.TYPE}" id="filter_{$i}">
    159           <span class="filter-title">
    160             <a href="#" class="removeFilter" title="{'remove this filter'|@translate}"><span>[x]</span></a>
    161             <input type="hidden" name="filters[{$i}][type]" value="{$filter.TYPE}"/>
    162             {$filter.CAPTION}
    163           </span>
    164          
    165           <span class="filter-cond">
    166             <select name="filters[{$i}][cond]">
    167               {html_options options=$options[$filter.TYPE].options selected=$filter.COND}
    168             </select>
    169           </span>
    170          
    171           <span class="filter-value">
    172           {if $filter.TYPE == 'tags'}
    173             <select name="filters[{$i}][value]" class="tagSelect">
    174             {foreach from=$filter.VALUE item=tag}
    175               <option value="{$tag.id}" class="selected">{$tag.name}</option>
    176             {/foreach}
    177             </select>
    178           {elseif $filter.TYPE == 'album'}
    179             <select name="filters[{$i}][value][]" class="albumSelect" multiple="multiple" data-placeholder="{'Select albums...'|@translate}">
    180               {html_options options=$all_albums selected=$filter.VALUE}
    181             </select>
    182           {elseif $filter.TYPE == 'level'}
    183             <select name="filters[{$i}][value]">
    184               {html_options options=$level_options selected=$filter.VALUE}
    185             </select>
    186           {else}
    187             <input type="text" name="filters[{$i}][value]" value="{$filter.VALUE}" size="30"/>
    188           {/if}
    189           {if $filter.TYPE == 'author'}
    190             <i>{'For "Is (not) in", separate each author by a comma'|@translate}</i>
    191           {/if}
    192           </span>
    193         </li>
    194         {counter}
    195       {/foreach}
     259    <ul id="filtersList">
     260    {foreach from=$filters item=filter}{strip}
     261      {if $filter.type == 'tags'}
     262        {capture assign='value'}{foreach from=$filter.value item=tag}<option value="{$tag.id}" class="selected">{$tag.name}</option>{/foreach}{/capture}
     263      {else}
     264        {assign var='value' value=$filter.value}
     265      {/if}
    196266     
    197       {footer_script}var i={$i};{/footer_script}
     267      {if $filter.type == 'limit'}
     268        {footer_script}
     269        limit_count=1;
     270        $("#addFilter option[value='limit']").attr('disabled','disabled');
     271        {/footer_script}
     272      {elseif $filter.type == 'level'}
     273        {footer_script}
     274        level_count=1;
     275        $("#addFilter option[value='level']").attr('disabled','disabled');
     276        {/footer_script}
     277      {/if}
     278     
     279      {footer_script}add_filter('{$filter.type}', '{$filter.cond}', '{$value|escape:javascript}');{/footer_script}
     280    {/strip}{/foreach}
    198281    </ul>
    199 
     282   
     283    <div>
     284      <b>{'Mode'|@translate} :</b>
     285      <label><input type="radio" name="filters[0][value]" value="and" {if $filter_mode=='and'}checked="checked"{/if}> AND</label>
     286      <label><input type="radio" name="filters[0][value]" value="or" {if $filter_mode=='or'}checked="checked"{/if}> OR</label>
     287      <input type="hidden" name="filters[0][type]" value="mode">
     288      <input type="hidden" name="filters[0][cond]" value="mode">
     289    </div>
     290   
    200291    <p class="actionButtons">
    201         <select id="addFilter">
    202           <option value="-1">{'Add a filter'|@translate}</option>
    203           <option disabled="disabled">------------------</option>
    204           <option value="tags">{'Tags'|@translate}</option>
    205           <option value="date">{'Date'|@translate}</option>
    206           <option value="name">{'Photo name'|@translate}</option>
    207           <option value="album">{'Album'|@translate}</option>
    208           <option value="author">{'Author'|@translate}</option>
    209           <option value="hit">{'Hits'|@translate}</option>
    210           <option value="rating_score">{'Rating score'|@translate}</option>
    211           <option value="level">{'Privacy level'|@translate}</option>
    212           <option value="limit">{'Max. number of photos'|@translate}</option>
    213         </select>
    214         <a id="removeFilters">{'Remove all filters'|@translate}</a>
    215         {if isset($new_smart)}<span class="new_smart">{'Add filters here'|@translate}</span>{/if}
     292      <select id="addFilter">
     293        <option value="-1">{'Add a filter'|@translate}</option>
     294        <option disabled="disabled">------------------</option>
     295        <option value="tags">{'Tags'|@translate}</option>
     296        <option value="date">{'Date'|@translate}</option>
     297        <option value="name">{'Photo name'|@translate}</option>
     298        <option value="album">{'Album'|@translate}</option>
     299        <option value="dimensions">{'Dimensions'|@translate}</option>
     300        <option value="author">{'Author'|@translate}</option>
     301        <option value="hit">{'Hits'|@translate}</option>
     302        <option value="rating_score">{'Rating score'|@translate}</option>
     303        <option value="level">{'Privacy level'|@translate}</option>
     304        <option value="limit">{'Max. number of photos'|@translate}</option>
     305      </select>
     306      <a id="removeFilters">{'Remove all filters'|@translate}</a>
     307      {if isset($new_smart)}<span class="new_smart">{'Add filters here'|@translate}</span>{/if}
    216308    </p>
    217309  </fieldset>
    218 
     310 
    219311  <p class="actionButtons" id="applyFilterBlock">
    220312    <input class="submit" type="submit" value="{'Submit'|@translate}" name="submitFilters"/>
     
    225317</form>
    226318</div>
     319
     320<div id="filtersRepo" style="display:none;">
     321  <!-- tags -->
     322  <div id="filter_tags">
     323  <li id="filter_iiii" class="filter_tags">
     324    <span class="filter-title">
     325      <a href="#" class="removeFilter" title="{'remove this filter'|@translate}"><span>[x]</span></a>
     326      <input type="hidden" name="filters[iiii][type]" value="tags"/>
     327      {$options.tags.name}
     328    </span>
     329   
     330    <span class="filter-cond">
     331      <select name="filters[iiii][cond]">
     332        {html_options options=$options.tags.options}
     333      </select>
     334    </span>
     335   
     336    <span class="filter-value">
     337      <select name="filters[iiii][value]" class="tagSelect">
     338      </select>
     339    </span>
     340  </li>
     341  </div>
     342 
     343  <!-- date -->
     344  <div id="filter_date">
     345  <li id="filter_iiii" class="filter_date">
     346    <span class="filter-title">
     347      <a href="#" class="removeFilter" title="{'remove this filter'|@translate}"><span>[x]</span></a>
     348      <input type="hidden" name="filters[iiii][type]" value="date"/>
     349      {$options.date.name}
     350    </span>
     351   
     352    <span class="filter-cond">
     353      <select name="filters[iiii][cond]">
     354        {html_options options=$options.date.options}
     355      </select>
     356    </span>
     357   
     358    <span class="filter-value">
     359      <input type="text" name="filters[iiii][value]" size="30"/>
     360    </span>
     361  </li>
     362  </div>
     363 
     364  <!-- name -->
     365  <div id="filter_name">
     366  <li id="filter_iiii" class="filter_name">
     367    <span class="filter-title">
     368      <a href="#" class="removeFilter" title="{'remove this filter'|@translate}"><span>[x]</span></a>
     369      <input type="hidden" name="filters[iiii][type]" value="name"/>
     370      {$options.name.name}
     371    </span>
     372   
     373    <span class="filter-cond">
     374      <select name="filters[iiii][cond]">
     375        {html_options options=$options.name.options}
     376      </select>
     377    </span>
     378   
     379    <span class="filter-value">
     380      <input type="text" name="filters[iiii][value]" size="30"/>
     381    </span>
     382  </li>
     383  </div>
     384 
     385  <!-- album -->
     386  <div id="filter_album">
     387  <li id="filter_iiii" class="filter_album">
     388    <span class="filter-title">
     389      <a href="#" class="removeFilter" title="{'remove this filter'|@translate}"><span>[x]</span></a>
     390      <input type="hidden" name="filters[iiii][type]" value="album"/>
     391      {$options.album.name}
     392    </span>
     393   
     394    <span class="filter-cond">
     395      <select name="filters[iiii][cond]">
     396        {html_options options=$options.album.options}
     397      </select>
     398    </span>
     399   
     400    <span class="filter-value">
     401      <select name="filters[iiii][value][]" class="albumSelect" multiple="multiple" data-placeholder="{'Select albums...'|@translate}">
     402        {html_options options=$all_albums}
     403      </select>
     404    </span>
     405  </li>
     406  </div>
     407 
     408  <!-- dimensions -->
     409  <div id="filter_dimensions">
     410  <li id="filter_iiii" class="filter_dimensions">
     411    <span class="filter-title">
     412      <a href="#" class="removeFilter" title="{'remove this filter'|@translate}"><span>[x]</span></a>
     413      <input type="hidden" name="filters[iiii][type]" value="dimensions"/>
     414      {$options.dimensions.name}
     415    </span>
     416
     417    <span class="filter-cond">
     418      <select name="filters[iiii][cond]">
     419        {html_options options=$options.dimensions.options}
     420      </select>
     421    </span>
     422
     423    <span class="filter-value">
     424      <span class="filter_dimension_info"></span>
     425      <span class="dimension_width">
     426        | <a class="dimensions-choice" data-type="width" data-min="{$dimensions.bounds.min_width}" data-max="{$dimensions.bounds.max_width}">{'Reset'|@translate}</a>
     427        <div class="filter_dimension_width_slider"></div>
     428      </span>
     429
     430      <span class="filter-value dimension_height">
     431        | <a class="dimensions-choice" data-type="height" data-min="{$dimensions.bounds.min_height}" data-max="{$dimensions.bounds.max_height}">{'Reset'|@translate}</a>
     432        <div class="filter_dimension_height_slider"></div>
     433      </span>
     434
     435      <span class="filter-value dimension_ratio">
     436{if isset($dimensions.ratio_portrait)}
     437        | <a class="dimensions-choice" data-type="ratio" data-min="{$dimensions.ratio_portrait.min}" data-max="{$dimensions.ratio_portrait.max}">{'Portrait'|@translate}</a>
     438{/if}
     439{if isset($dimensions.ratio_square)}
     440        | <a class="dimensions-choice" data-type="ratio" data-min="{$dimensions.ratio_square.min}" data-max="{$dimensions.ratio_square.max}">{'square'|@translate}</a>
     441{/if}
     442{if isset($dimensions.ratio_landscape)}
     443        | <a class="dimensions-choice" data-type="ratio" data-min="{$dimensions.ratio_landscape.min}" data-max="{$dimensions.ratio_landscape.max}">{'Landscape'|@translate}</a>
     444{/if}
     445{if isset($dimensions.ratio_panorama)}
     446        | <a class="dimensions-choice" data-type="ratio" data-min="{$dimensions.ratio_panorama.min}" data-max="{$dimensions.ratio_panorama.max}">{'Panorama'|@translate}</a>
     447{/if}
     448        | <a class="dimensions-choice" data-type="ratio" data-min="{$dimensions.bounds.min_ratio}" data-max="{$dimensions.bounds.max_ratio}">{'Reset'|@translate}</a>
     449        <div class="filter_dimension_ratio_slider"></div>
     450      </span>
     451    </span>
     452
     453    <input type="hidden" name="filters[iiii][value][min]" value="">
     454    <input type="hidden" name="filters[iiii][value][max]" value="">
     455  </li>
     456  </div>
     457 
     458  <!-- author -->
     459  <div id="filter_author">
     460  <li id="filter_iiii" class="filter_author">
     461    <span class="filter-title">
     462      <a href="#" class="removeFilter" title="{'remove this filter'|@translate}"><span>[x]</span></a>
     463      <input type="hidden" name="filters[iiii][type]" value="author"/>
     464      {$options.author.name}
     465    </span>
     466   
     467    <span class="filter-cond">
     468      <select name="filters[iiii][cond]">
     469        {html_options options=$options.author.options}
     470      </select>
     471    </span>
     472   
     473    <span class="filter-value">
     474      <input type="text" name="filters[iiii][value]" size="30"/>
     475      <i>{'For "Is (not) in", separate each author by a comma'|@translate}</i>
     476    </span>
     477  </li>
     478  </div>
     479 
     480  <!-- hit -->
     481  <div id="filter_hit">
     482  <li id="filter_iiii" class="filter_hit">
     483    <span class="filter-title">
     484      <a href="#" class="removeFilter" title="{'remove this filter'|@translate}"><span>[x]</span></a>
     485      <input type="hidden" name="filters[iiii][type]" value="hit"/>
     486      {$options.hit.name}
     487    </span>
     488   
     489    <span class="filter-cond">
     490      <select name="filters[iiii][cond]">
     491        {html_options options=$options.hit.options}
     492      </select>
     493    </span>
     494   
     495    <span class="filter-value">
     496      <input type="text" name="filters[iiii][value]" size="5"/>
     497    </span>
     498  </li>
     499  </div>
     500 
     501  <!-- rating_score -->
     502  <div id="filter_rating_score">
     503  <li id="filter_iiii" class="filter_rating_score">
     504    <span class="filter-title">
     505      <a href="#" class="removeFilter" title="{'remove this filter'|@translate}"><span>[x]</span></a>
     506      <input type="hidden" name="filters[iiii][type]" value="rating_score"/>
     507      {$options.rating_score.name}
     508    </span>
     509   
     510    <span class="filter-cond">
     511      <select name="filters[iiii][cond]">
     512        {html_options options=$options.rating_score.options}
     513      </select>
     514    </span>
     515   
     516    <span class="filter-value">
     517      <input type="text" name="filters[iiii][value]" size="5"/>
     518    </span>
     519  </li>
     520  </div>
     521 
     522  <!-- level -->
     523  <div id="filter_level">
     524  <li id="filter_iiii" class="filter_level">
     525    <span class="filter-title">
     526      <a href="#" class="removeFilter" title="{'remove this filter'|@translate}"><span>[x]</span></a>
     527      <input type="hidden" name="filters[iiii][type]" value="level"/>
     528      {$options.level.name}
     529    </span>
     530   
     531    <input type="hidden" name="filters[iiii][cond]" value="level"/>
     532   
     533    <span class="filter-value">
     534      <select name="filters[iiii][value]">
     535        {html_options options=$level_options}
     536      </select>
     537    </span>
     538  </li>
     539  </div>
     540 
     541  <!-- limit -->
     542  <div id="filter_limit">
     543  <li id="filter_iiii" class="filter_limit">
     544    <span class="filter-title">
     545      <a href="#" class="removeFilter" title="{'remove this filter'|@translate}"><span>[x]</span></a>
     546      <input type="hidden" name="filters[iiii][type]" value="limit"/>
     547      {$options.limit.name}
     548    </span>
     549   
     550    <input type="hidden" name="filters[iiii][cond]" value="limit"/>
     551   
     552    <span class="filter-value">
     553      <input type="text" name="filters[iiii][value]" size="5"/>
     554    </span>
     555  </li>
     556  </div>
     557</div>
  • extensions/SmartAlbums/admin/template/cat_list.tpl

    r16104 r19446  
    6060        <strong><a href="{$category.U_CHILDREN}" title="{'manage sub-albums'|@translate}">{$category.NAME}</a></strong>
    6161        <img src="{$SMART_PATH}admin/template/lightning.png">
     62        {'%d photos'|@translate|sprintf:$category.IMG_COUNT}
    6263      </p>
    6364
    6465      <p class="albumActions">
    6566        <a href="{$category.U_EDIT}">{'Edit'|@translate}</a>
    66         | <a href="{$category.U_SMART}">{'Regenerate photos list of this SmartAlbum'|@translate}</a>
    67         {if isset($category.U_MANAGE_ELEMENTS) }
    68         | <a href="{$category.U_MANAGE_ELEMENTS}">{'manage album photos'|@translate}</a>
    69         {/if}
     67        | <a href="{$category.U_SMART}" title="{$category.LAST_UPDATE}">{'Regenerate photos list of this SmartAlbum'|@translate}</a>
    7068        {if isset($category.U_DELETE) }
    7169        | <a href="{$category.U_DELETE}" onclick="return confirm('{'Are you sure?'|@translate|@escape:javascript}');">{'delete album'|@translate}</a>
  • extensions/SmartAlbums/admin/template/config.tpl

    r16939 r19446  
    2323
    2424<div class="titrePage">
    25         <h2>SmartAlbums</h2>
     25  <h2>SmartAlbums</h2>
    2626</div>
    2727
    2828<form method="post" action="" class="properties">
    29         <fieldset id="commentsConf">
    30                 <ul>                   
    31                         <li>
     29  <fieldset id="commentsConf">
     30    <ul>
     31      <li>
    3232        <label>
    3333          <input type="checkbox" name="update_on_upload" value="true" {if $update_on_upload}checked="checked"{/if}/>
     
    3535          <a class="showInfo" title="{'can cause slowdowns'|@translate}">i</a>
    3636        </label>
    37                         </li>
     37      </li>
     38      <li>
     39        <label>
     40          <input type="checkbox" name="update_on_date" value="true" {if $update_on_date}checked="checked"{/if}/>
     41          {assign var=input value='<input type="text" name="update_timeout" size="2" value="'|cat:$update_timeout|cat:'"/>'}
     42          <b>{'Update albums every %s days'|@translate|sprintf:$input}</b>
     43        </label>
     44      </li>
    3845      <li>
    3946        <label>
     
    4249          <a class="showInfo" title="{'SmartAlbums are considered private for everyone, and a user can see it\'s content only if available in another album he has access to.'|@translate}">i</a>
    4350        </label>
    44                         </li>
    45                 </ul>
    46         </fieldset>
    47                
    48         <p class="formButtons"><input class="submit" type="submit" value="{'Submit'|@translate}" name="submit" /></p>
     51      </li>
     52    </ul>
     53  </fieldset>
     54   
     55  <p class="formButtons"><input class="submit" type="submit" value="{'Submit'|@translate}" name="submit" /></p>
    4956</form>
  • extensions/SmartAlbums/admin/template/style.css

    r17677 r19446  
    33  vertical-align:bottom;
    44}
    5 #batchManagerGlobal #filterList li.token-input-token {
     5#batchManagerGlobal #filtersList li.token-input-token {
    66  margin-bottom:0px !important;
    77  padding-top:0;
    88}
    9 #batchManagerGlobal #filterList li.token-input-input-token {
     9#batchManagerGlobal #filtersList li.token-input-input-token {
    1010  margin-bottom:-3px !important;
     11}
     12
     13#batchManagerGlobal .filter_dimensions .ui-slider-horizontal {
     14    margin: 5px 0 10px;
     15    width: 500px;
    1116}
    1217
     
    1924}
    2025
    21 #filterList li {
     26#filtersList li {
    2227  padding:2px;
    2328  border-bottom:1px dotted rgba(100, 100, 100, 0.5);
     29  display:block;
    2430}
    25 #filterList li span {
     31#filtersList li>span {
    2632  display:inline-block;
    2733}
    28 #filterList li span * {
     34#filtersList li span * {
    2935  vertical-align:middle;
    3036}
     
    3945.filter-cond {
    4046  width:220px;
    41 }
    42 
    43 .filter_limit .filter-cond, .filter_level .filter-cond {
    44   display:none !important;
    4547}
    4648
  • extensions/SmartAlbums/include/functions.inc.php

    r17677 r19446  
    2929        );
    3030    }
    31     mass_inserts_ignore(
     31    mass_inserts(
    3232      IMAGE_CATEGORY_TABLE,
    3333      array_keys($datas[0]),
    34       $datas
     34      $datas,
     35      array('ignore'=>true)
    3536      );
    3637  }
     
    4950    set_random_representant(array($cat_id));
    5051  }
     52 
     53  $query = '
     54UPDATE '.CATEGORIES_TABLE.'
     55  SET smart_update = NOW()
     56  WHERE id = '.$cat_id.'
     57;';
     58  pwg_query($query);
    5159 
    5260  return $images;
     
    6472  if ( defined('SMART_NOT_UPDATE') OR !$conf['SmartAlbums']['update_on_upload'] ) return;
    6573 
    66   /* get categories with smart filters */
     74  // get categories with smart filters
    6775  $query = '
    6876SELECT DISTINCT id
     
    7280;';
    7381 
    74   /* regenerate photo list */
     82  // regenerate photo list
    7583  $smart_cats = array_from_query($query, 'id');
    7684  array_map('smart_make_associations', $smart_cats);
     
    115123    return array();
    116124  }
    117    
     125 
     126  $mode = 'and';
     127 
    118128  /* build constrains */
    119129  ## generate 'join', 'where' arrays and 'limit' string to create the SQL query
     
    249259            $where[] = 'name NOT LIKE "%'.$filter['value'].'"';
    250260            break;
     261          case 'regex':
     262            $where[] = 'name REGEXP "'.$filter['value'].'"';
     263            break;
    251264        }
    252265       
     
    327340      }
    328341     
     342      // dimensions
     343      case 'dimensions':
     344      {
     345        $filter['value'] = explode(',', $filter['value']);
     346       
     347        switch ($filter['cond'])
     348        {
     349          case 'width':
     350            $where[] = 'width >= '.$filter['value'][0].' AND width <= '.$filter['value'][1];
     351            break;
     352          case 'height':
     353            $where[] = 'height >= '.$filter['value'][0].' AND height <= '.$filter['value'][1];
     354            break;
     355          case 'ratio':
     356            $where[] = 'width/height >= '.$filter['value'][0].' AND width/height < '.($filter['value'][1]+0.01);
     357            break;
     358        }
     359      }
     360     
    329361      // author
    330362      case 'author':
     
    348380            $where[] = 'author NOT IN('.$filter['value'].')';
    349381            break;
     382          case 'regex':
     383            $where[] = 'author REGEXP "'.$filter['value'].'"';
     384            break;
    350385        }
    351386       
     
    396431      {
    397432        $limit = '0, '.$filter['value'];
     433        break;
     434      }
     435     
     436      // mode
     437      case 'mode':
     438      {
     439        $mode = $filter['value'];
    398440        break;
    399441      }
     
    415457      $MainQuery.= '
    416458  WHERE
    417     '.implode("\n    AND ", $where);
     459    '.implode("\n    ".$mode." ", $where);
    418460    }
    419461
     
    424466;';
    425467
    426   // file_put_contents(SMART_PATH.'query.sql', $MainQuery);
     468  if (defined('SMART_DEBUG'))
     469  {
     470    file_put_contents(SMART_PATH.'dump_filters.txt', print_r($filters, true));
     471    file_put_contents(SMART_PATH.'dump_query.sql', $MainQuery);
     472  }
     473 
    427474  return array_from_query($MainQuery, 'id');
    428475}
     
    442489  if (!isset($level_is_set)) $level_is_set = false;
    443490 
    444   # tags
    445   if ($filter['type'] == 'tags')
    446   {
    447     if ($filter['value'] == null)
     491  switch ($filter['type'])
     492  {
     493    # tags
     494    case 'tags':
     495    {
     496      if ($filter['value'] == null)
     497      {
     498        $error = true;
     499        array_push($page['errors'], l10n('No tag selected'));
     500      }
     501      else
     502      {
     503        $filter['value'] = implode(',', get_tag_ids($filter['value']));
     504      }
     505      break;
     506    }
     507    # date
     508    case 'date':
     509    {
     510      if (!preg_match('#([0-9]{4})-([0-9]{2})-([0-9]{2})#', $filter['value']))
     511      {
     512        $error = true;
     513        array_push($page['errors'], l10n('Date string is malformed'));
     514      }
     515      break;
     516    }
     517    # name
     518    case 'name':
     519    {
     520      if (empty($filter['value']))
     521      {
     522        $error = true;
     523        array_push($page['errors'], l10n('Name is empty'));
     524      }
     525      else if ( $filter['cond']=='regex' and @preg_match('/'.$filter['value'].'/', null)===false )
     526      {
     527        $error = true;
     528        array_push($page['errors'], l10n('Regex is malformed'));
     529      }
     530      break;
     531    }
     532    # album
     533    case 'album':
     534    {
     535      if (@$filter['value'] == null)
     536      {
     537        $error = true;
     538        array_push($page['errors'], l10n('No album selected'));
     539      }
     540      else
     541      {
     542        $filter['value'] = implode(',', $filter['value']);
     543      }
     544      break;
     545    }
     546    # dimensions
     547    case 'dimensions':
     548    {
     549      if ( empty($filter['value']['min']) or empty($filter['value']['max']) )
     550      {
     551        $error = true;
     552      }
     553      else
     554      {
     555        $filter['value'] = $filter['value']['min'].','.$filter['value']['max'];
     556      }
     557      break;
     558    }
     559    # author
     560    case 'author':
     561    {
     562      if (empty($filter['value']))
     563      {
     564        $error = true;
     565        array_push($page['errors'], l10n('Author is empty'));
     566      }
     567      else if ( $filter['cond']=='regex' and @preg_match('/'.$filter['value'].'/', null)===false )
     568      {
     569        $error = true;
     570        array_push($page['errors'], l10n('Regex is malformed'));
     571      }
     572      else
     573      {
     574        $filter['value'] = preg_replace('#([ ]?),([ ]?)#', ',', $filter['value']);
     575      }
     576      break;
     577    }
     578    # hit
     579    case 'hit':
     580    {
     581      if (!preg_match('#([0-9]{1,})#', $filter['value']))
     582      {
     583        $error = true;
     584        array_push($page['errors'], l10n('Hits must be an integer'));
     585      }
     586      break;
     587    }
     588    # rating_score
     589    case 'rating_score':
     590    {
     591      if (!preg_match('#([0-9]{1,})#', $filter['value']))
     592      {
     593        $error = true;
     594        array_push($page['errors'], l10n('Rating score must be an integer'));
     595      }
     596      break;
     597    }
     598    # level
     599    case 'level':
     600    {
     601      if ($level_is_set == true) // only one level is allowed, first is saved
     602      {
     603        $error = true;
     604        array_push($page['errors'], l10n('You can\'t use more than one level filter'));
     605      }
     606      else
     607      {
     608        $filter['cond'] = 'level';
     609        $level_is_set = true;
     610      }
     611      break;
     612    }
     613    # limit
     614    case 'limit':
     615    {
     616      if ($limit_is_set == true) // only one limit is allowed, first is saved
     617      {
     618        $error = true;
     619        array_push($page['errors'], l10n('You can\'t use more than one limit filter'));
     620      }
     621      else if (!preg_match('#([0-9]{1,})#', $filter['value']))
     622      {
     623        $error = true;
     624        array_push($page['errors'], l10n('Limit must be an integer'));
     625      }
     626      else
     627      {
     628        $filter['cond'] = 'level';
     629        $limit_is_set = true;
     630      }
     631      break;
     632    }
     633    # mode
     634    case 'mode':
     635    {
     636      $filter['cond'] = 'mode';
     637      break;
     638    }
     639   
     640    default:
    448641    {
    449642      $error = true;
    450       array_push($page['errors'], l10n('No tag selected'));
    451     }
    452     else
    453     {
    454       $filter['value'] = implode(',', get_tag_ids($filter['value']));
    455     }
    456   }
    457   # date
    458   else if ($filter['type'] == 'date')
    459   {
    460     if (!preg_match('#([0-9]{4})-([0-9]{2})-([0-9]{2})#', $filter['value']))
    461     {
    462       $error = true;
    463       array_push($page['errors'], l10n('Date string is malformed'));
    464     }
    465   }
    466   # name
    467   else if ($filter['type'] == 'name')
    468   {
    469     if (empty($filter['value']))
    470     {
    471       $error = true;
    472       array_push($page['errors'], l10n('Name is empty'));
    473     }
    474   }
    475   # album
    476   else if ($filter['type'] == 'album')
    477   {
    478     if (@$filter['value'] == null)
    479     {
    480       $error = true;
    481       array_push($page['errors'], l10n('No album selected'));
    482     }
    483     else
    484     {
    485       $filter['value'] = implode(',', $filter['value']);
    486     }
    487   }
    488   # author
    489   else if ($filter['type'] == 'author')
    490   {
    491     if (empty($filter['value']))
    492     {
    493       $error = true;
    494       array_push($page['errors'], l10n('Author is empty'));
    495     }
    496     else
    497     {
    498       $filter['value'] = preg_replace('#([ ]?),([ ]?)#', ',', $filter['value']);
    499     }
    500   }
    501   # hit
    502   else if ($filter['type'] == 'hit')
    503   {
    504     if (!preg_match('#([0-9]{1,})#', $filter['value']))
    505     {
    506       $error = true;
    507       array_push($page['errors'], l10n('Hits must be an integer'));
    508     }
    509   }
    510   # rating_score
    511   else if ($filter['type'] == 'rating_score')
    512   {
    513     if (!preg_match('#([0-9]{1,})#', $filter['value']))
    514     {
    515       $error = true;
    516       array_push($page['errors'], l10n('Rating score must be an integer'));
    517     }
    518   }
    519   # level
    520   else if ($filter['type'] == 'level')
    521   {
    522     if ($level_is_set == true) // only one level is allowed, first is saved
    523     {
    524       $error = true;
    525       array_push($page['errors'], l10n('You can\'t use more than one level filter'));
    526     }
    527     else
    528     {
    529       $level_is_set = true;
    530     }
    531   }
    532   # limit
    533   else if ($filter['type'] == 'limit')
    534   {
    535     if (!preg_match('#([0-9]{1,})#', $filter['value']))
    536     {
    537       $error = true;
    538       array_push($page['errors'], l10n('Limit must be an integer'));
    539     }
    540     else if ($limit_is_set == true) // only one limit is allowed, first is saved
    541     {
    542       $error = true;
    543       array_push($page['errors'], l10n('You can\'t use more than one limit filter'));
    544     }
    545     else
    546     {
    547       $limit_is_set = true;
    548     }
    549   }
    550  
    551   # out
     643      break;
     644    }
     645  }
     646 
     647 
    552648  if ($error == false)
    553649  {
     
    560656}
    561657
    562 
    563 /**
    564  * inserts multiple lines in a table, ignore duplicate entries
    565  * @param string table_name
    566  * @param array dbfields
    567  * @param array inserts
    568  * @return void
    569  */
    570 function mass_inserts_ignore($table_name, $dbfields, $datas)
    571 {
    572   if (count($datas) != 0)
    573   {
    574     $first = true;
    575 
    576     $query = 'SHOW VARIABLES LIKE \'max_allowed_packet\'';
    577     list(, $packet_size) = pwg_db_fetch_row(pwg_query($query));
    578     $packet_size = $packet_size - 2000; // The last list of values MUST not exceed 2000 character*/
    579     $query = '';
    580 
    581     foreach ($datas as $insert)
    582     {
    583       if (strlen($query) >= $packet_size)
    584       {
    585         pwg_query($query);
    586         $first = true;
    587       }
    588 
    589       if ($first)
    590       {
    591         $query = '
    592 INSERT IGNORE INTO '.$table_name.'
    593   ('.implode(',', $dbfields).')
    594   VALUES';
    595         $first = false;
    596       }
    597       else
    598       {
    599         $query .= '
    600   , ';
    601       }
    602 
    603       $query .= '(';
    604       foreach ($dbfields as $field_id => $dbfield)
    605       {
    606         if ($field_id > 0)
    607         {
    608           $query .= ',';
    609         }
    610 
    611         if (!isset($insert[$dbfield]) or $insert[$dbfield] === '')
    612         {
    613           $query .= 'NULL';
    614         }
    615         else
    616         {
    617           $query .= "'".$insert[$dbfield]."'";
    618         }
    619       }
    620       $query .= ')';
    621     }
    622     pwg_query($query);
    623   }
    624 }
    625658
    626659/**
     
    636669}
    637670
     671/**
     672 * update images list periodically
     673 */
     674function smart_periodic_update()
     675{
     676  global $conf;
     677 
     678  // we only search for old albums every hour, nevermind which user is connected
     679  if ($conf['SmartAlbums']['last_update'] > time() - 3600) return;
     680 
     681  $conf['SmartAlbums']['last_update'] = time();
     682  conf_update_param('SmartAlbums', serialize($conf['SmartAlbums']));
     683 
     684  // get categories with smart filters
     685  $query = '
     686SELECT DISTINCT id
     687  FROM '.CATEGORIES_TABLE.' AS c
     688    INNER JOIN '.CATEGORY_FILTERS_TABLE.' AS cf
     689    ON c.id = cf.category_id
     690  WHERE smart_update < DATE_SUB(NOW(), INTERVAL '.$conf['SmartAlbums']['update_timeout'].' DAY)
     691;';
     692 
     693  // regenerate photo list
     694  $smart_cats = array_from_query($query, 'id');
     695  array_map('smart_make_associations', $smart_cats);
     696}
     697
    638698?>
  • extensions/SmartAlbums/include/install.inc.php

    r17716 r19446  
    1111    $smart_default_config = serialize(array(
    1212      'update_on_upload' => false,
     13      'update_on_date' => true,
     14      'update_timeout' => 3,
    1315      'show_list_messages' => true,
    1416      'smart_is_forbidden' => true,
     17      'last_update' => 0,
    1518      ));
    1619   
     
    2528    {
    2629      $new_conf['smart_is_forbidden'] = true;
    27       conf_update_param('SmartAlbums', serialize($new_conf));
    28       $conf['SmartAlbums'] = serialize($new_conf);
    2930    }
     31    // new params in 2.1.0
     32    if (!isset($new_conf['update_on_date']))
     33    {
     34      $new_conf['update_on_date'] = true;
     35      $new_conf['update_timeout'] = 3;
     36      $new_conf['last_update'] = 0;
     37    }
     38    conf_update_param('SmartAlbums', serialize($new_conf));
     39    $conf['SmartAlbums'] = serialize($new_conf);
    3040  }
    3141 
     
    4555  {     
    4656    pwg_query('ALTER TABLE `' . IMAGE_CATEGORY_TABLE . '` ADD `smart` ENUM(\'true\', \'false\') NOT NULL DEFAULT \'false\';');
     57  }
     58 
     59  // new column on category table
     60  $result = pwg_query('SHOW COLUMNS FROM `' . CATEGORIES_TABLE . '` LIKE "smart_update";');
     61  if (!pwg_db_num_rows($result))
     62  {     
     63    pwg_query('ALTER TABLE `' . CATEGORIES_TABLE . '` ADD `smart_update` DATETIME NOT NULL;');
    4764  }
    4865 
     
    6885    foreach ($name_changes as $old => $new)
    6986    {
    70       pwg_query('UPDATE `' . $prefixeTable . 'category_filters` SET cond = "'.$new.'" WHERE cond = "'.$old.'";');
     87      pwg_query('UPDATE `' . $prefixeTable . 'category_filters` SET cond = "'.$new.'" WHERE type = "date" AND cond = "'.$old.'";');
    7188    }
    7289  }
  • extensions/SmartAlbums/language/en_UK/plugin.lang.php

    r18622 r19446  
    2323$lang['Doesn\'t begin with'] = 'Doesn\'t begin with';
    2424$lang['Doesn\'t end with'] = 'Doesn\'t end with';
     25$lang['Regular expression'] = 'Regular expression';
    2526$lang['Is'] = 'Is';
    2627$lang['Is in'] = 'Is in';
     
    4445$lang['Limit must be an integer'] = 'Limit must be an integer';
    4546$lang['Rating score must be an integer'] = 'Rating score must be an integer';
     47$lang['Regex is malformed'] = 'Regex is malformed';
    4648$lang['You can\'t use more than one limit filter'] = 'You can\'t use more than one limit filter';
    4749$lang['You can\'t use more than one level filter'] = 'You can\'t use more than one level filter';
     
    6062$lang['Exclude SmartAlbums from permissions management'] = 'Exclude SmartAlbums from permissions management';
    6163$lang['SmartAlbums are considered private for everyone, and a user can see it\'s content only if available in another album he has access to.'] = 'SmartAlbums are considered private for everyone, and a user can see it\'s content only if available in another album he has access to.';
     64$lang['Update albums every %s days'] = 'Update albums every %s days';
    6265
    6366?>
  • extensions/SmartAlbums/language/fr_FR/plugin.lang.php

    r19074 r19446  
    2323$lang['Doesn\'t begin with'] = 'Ne commence pas par';
    2424$lang['Doesn\'t end with'] = 'Ne fini pas par';
     25$lang['Regular expression'] = 'Expression régulière';
    2526$lang['Is'] = 'Est';
    2627$lang['Is in'] = 'Est dans';
     
    4445$lang['Limit must be an integer'] = 'La nombre d\'éléments doit être un entier';
    4546$lang['Rating score must be an integer'] = 'Le score doit être un entier';
     47$lang['Regex is malformed'] = 'Regex malformée';
    4648$lang['You can\'t use more than one limit filter'] = 'Vous ne pouvez choisir qu\'une seule limite de nombre d\'éléments';
    4749$lang['You can\'t use more than one level filter'] = 'Vous ne pouvez choisir qu\'un seul niveau de confidentialité';
     
    6062$lang['Exclude SmartAlbums from permissions management'] = 'Exclure les SmartAlbums de la gestion des droits d\'accès';
    6163$lang['SmartAlbums are considered private for everyone, and a user can see it\'s content only if available in another album he has access to.'] = 'Les SmartAlbums sont considérés comme privés pour tout le monde, et un utilisateur ne peut voir leur contenu que si disponible dans un autre album auquel il a accès.';
     64$lang['Update albums every %s days'] = 'Mettre à jour les albums tous les %s jours';
    6265
    6366?>
  • extensions/SmartAlbums/main.inc.php

    r17821 r19446  
    1212global $prefixeTable;
    1313
    14 define('SMART_PATH',    PHPWG_PLUGINS_PATH . 'SmartAlbums/');
     14define('SMART_PATH',     PHPWG_PLUGINS_PATH . 'SmartAlbums/');
    1515define('CATEGORY_FILTERS_TABLE', $prefixeTable . 'category_filters');
    16 define('SMART_ADMIN',   get_root_url() . 'admin.php?page=plugin-SmartAlbums');
    17 define('SMART_VERSION', '2.0.4');
     16define('SMART_ADMIN',    get_root_url() . 'admin.php?page=plugin-SmartAlbums');
     17define('SMART_VERSION',  'auto');
     18//define('SMART_DEBUG',    true);
    1819
    1920
     21add_event_handler('init', 'smart_init');
     22add_event_handler('init', 'smart_periodic_update');
    2023add_event_handler('invalidate_user_cache', 'smart_make_all_associations');
    21 add_event_handler('init', 'smart_init');
    2224
    2325if (defined('IN_ADMIN'))
     
    4143 
    4244  if (
     45    SMART_VERSION == 'auto' or
    4346    $pwg_loaded_plugins['SmartAlbums']['version'] == 'auto' or
    4447    version_compare($pwg_loaded_plugins['SmartAlbums']['version'], SMART_VERSION, '<')
     
    4851    smart_albums_install();
    4952   
    50     if ($pwg_loaded_plugins['SmartAlbums']['version'] != 'auto')
     53    if ( $pwg_loaded_plugins['SmartAlbums']['version'] != 'auto' and SMART_VERSION != 'auto' )
    5154    {
    5255      $query = '
  • extensions/SmartAlbums/maintain.inc.php

    r17716 r19446  
    2424  pwg_query('DROP TABLE `' . $prefixeTable . 'category_filters`;');
    2525  pwg_query('ALTER TABLE `' . IMAGE_CATEGORY_TABLE . '` DROP `smart`;');
     26  pwg_query('ALTER TABLE `' . CATEGORIES_TABLE . '` DROP `smart_update`;');
    2627  pwg_query('DELETE FROM `' . CONFIG_TABLE . '` WHERE param = \'SmartAlbums\' LIMIT 1;');
    2728}
Note: See TracChangeset for help on using the changeset viewer.