+sub _filter_hash{
+ my ($tablename,$filter_input, $searchtype)=@_;
+ my (@values, @keys);
+ my $columns= _get_columns($tablename);
+ my @columns_filtered= _filter_columns($tablename,$searchtype);
+
+ #Filter Primary Keys of table
+ my $elements=join "|",@columns_filtered;
+ foreach my $field (grep {/\b($elements)\b/} keys %$filter_input){
+ ## supposed to be a hash of simple values, hashes of arrays could be implemented
+ $filter_input->{$field}=format_date_in_iso($filter_input->{$field})
+ if $columns->{$field}{Type}=~/date/ &&
+ $filter_input->{$field} !~C4::Dates->regexp("iso");
+ my ($tmpkeys, $localvalues)=_Process_Operands($filter_input->{$field},"$tablename.$field",$searchtype,$columns);
+ if (@$tmpkeys){
+ push @values, @$localvalues;
+ push @keys, @$tmpkeys;
+ }
+ }
+ if (@keys){
+ return (\@keys,\@values);
+ }
+ else {
+ return ();
+ }
+}
+
+sub _filter_string{
+ my ($tablename,$filter_input, $searchtype,$filtercolumns)=@_;
+ return () unless($filter_input);
+ my @operands=split /\s+/,$filter_input;
+
+ # An act of desperation
+ $searchtype = 'contain' if @operands > 1 && $searchtype =~ /start_with/o;
+
+ my @columns_filtered= _filter_columns($tablename,$searchtype,$filtercolumns);
+ my $columns= _get_columns($tablename);
+ my (@values,@keys);
+ foreach my $operand (@operands){
+ my @localkeys;
+ foreach my $field (@columns_filtered){
+ my ($tmpkeys, $localvalues)=_Process_Operands($operand,"$tablename.$field",$searchtype,$columns);
+ if ($tmpkeys){
+ push @values,@$localvalues;
+ push @localkeys,@$tmpkeys;
+ }
+ }
+ my $sql= join (' OR ', @localkeys);
+ push @keys, $sql;
+ }
+
+ if (@keys){
+ return (\@keys,\@values);
+ }
+ else {
+ return ();
+ }
+}
+sub _Process_Operands{
+ my ($operand, $field, $searchtype,$columns)=@_;
+ my @values;
+ my @tmpkeys;
+ my @localkeys;
+
+ $operand = [$operand] unless ref $operand eq 'ARRAY';
+ foreach (@$operand) {
+ push @tmpkeys, " $field = ? ";
+ push @values, $_;
+ }
+ #By default, exact search
+ if (!$searchtype ||$searchtype eq "exact"){
+ return \@tmpkeys,\@values;
+ }
+ my $col_field=(index($field,".")>0?substr($field, index($field,".")+1):$field);
+ if ($field=~/(?<!zip)code|(?<!card)number/ && $searchtype ne "exact"){
+ push @tmpkeys,(" $field= '' ","$field IS NULL");
+ }
+ if ($columns->{$col_field}->{Type}=~/varchar|text/i){
+ my @localvaluesextended;
+ if ($searchtype eq "contain"){
+ foreach (@$operand) {
+ push @tmpkeys,(" $field LIKE ? ");
+ push @localvaluesextended,("\%$_\%") ;
+ }
+ }
+ if ($searchtype eq "field_start_with"){
+ foreach (@$operand) {
+ push @tmpkeys,("$field LIKE ?");
+ push @localvaluesextended, ("$_\%") ;
+ }
+ }
+ if ($searchtype eq "start_with"){
+ foreach (@$operand) {
+ push @tmpkeys,("$field LIKE ?","$field LIKE ?");
+ push @localvaluesextended, ("$_\%", " $_\%") ;
+ }
+ }
+ push @values,@localvaluesextended;
+ }
+ push @localkeys,qq{ (}.join(" OR ",@tmpkeys).qq{) };
+ return (\@localkeys,\@values);
+}