package Koha::AdditionalField; use Modern::Perl; use base qw(Class::Accessor); use C4::Context; __PACKAGE__->mk_accessors(qw( id tablename name authorised_value_category marcfield searchable values )); sub new { my ( $class, $args ) = @_; my $additional_field = { id => $args->{id} // q||, tablename => $args->{tablename} // q||, name => $args->{name} // q||, authorised_value_category => $args->{authorised_value_category} // q||, marcfield => $args->{marcfield} // q||, searchable => $args->{searchable} // 0, values => $args->{values} // {}, }; my $self = $class->SUPER::new( $additional_field ); bless $self, $class; return $self; } sub fetch { my ( $self ) = @_; my $dbh = C4::Context->dbh; my $field_id = $self->id; return unless $field_id; my $data = $dbh->selectrow_hashref( q| SELECT id, tablename, name, authorised_value_category, marcfield, searchable FROM additional_fields WHERE id = ? |, {}, ( $field_id ) ); die "This additional field does not exist (id=$field_id)" unless $data; $self->{id} = $data->{id}; $self->{tablename} = $data->{tablename}; $self->{name} = $data->{name}; $self->{authorised_value_category} = $data->{authorised_value_category}; $self->{marcfield} = $data->{marcfield}; $self->{searchable} = $data->{searchable}; return $self; } sub update { my ( $self ) = @_; die "There is no id defined for this additional field. I cannot update it" unless $self->{id}; my $dbh = C4::Context->dbh; local $dbh->{RaiseError} = 1; return $dbh->do(q| UPDATE additional_fields SET name = ?, authorised_value_category = ?, marcfield = ?, searchable = ? WHERE id = ? |, {}, ( $self->{name}, $self->{authorised_value_category}, $self->{marcfield}, $self->{searchable}, $self->{id} ) ); } sub delete { my ( $self ) = @_; return unless $self->{id}; my $dbh = C4::Context->dbh; local $dbh->{RaiseError} = 1; return $dbh->do(q| DELETE FROM additional_fields WHERE id = ? |, {}, ( $self->{id} ) ); } sub insert { my ( $self ) = @_; my $dbh = C4::Context->dbh; local $dbh->{RaiseError} = 1; $dbh->do(q| INSERT INTO additional_fields ( tablename, name, authorised_value_category, marcfield, searchable ) VALUES ( ?, ?, ?, ?, ? ) |, {}, ( $self->{tablename}, $self->{name}, $self->{authorised_value_category}, $self->{marcfield}, $self->{searchable} ) ); $self->{id} = $dbh->{mysql_insertid}; } sub insert_values { my ( $self ) = @_; my $dbh = C4::Context->dbh; local $dbh->{RaiseError} = 1; while ( my ( $record_id, $value ) = each %{$self->{values}} ) { next unless defined $value; my $updated = $dbh->do(q| UPDATE additional_field_values SET value = ? WHERE field_id = ? AND record_id = ? |, {}, ( $value, $self->{id}, $record_id )); if ( $updated eq '0E0' ) { $dbh->do(q| INSERT INTO additional_field_values( field_id, record_id, value ) VALUES( ?, ?, ?) |, {}, ( $self->{id}, $record_id, $value )); } } } sub fetch_values { my ( $self, $args ) = @_; my $record_id = $args->{record_id}; my $dbh = C4::Context->dbh; my $values = $dbh->selectall_arrayref( q| SELECT * FROM additional_fields af, additional_field_values afv WHERE af.id = afv.field_id AND af.tablename = ? AND af.name = ? | . ( $record_id ? q|AND afv.record_id = ?| : '' ), {Slice => {}}, ( $self->{tablename}, $self->{name}, ($record_id ? $record_id : () ) ) ); $self->{values} = {}; for my $v ( @$values ) { $self->{values}{$v->{record_id}} = $v->{value}; } } sub delete_values { my ($self, $args) = @_; my $record_id = $args->{record_id}; my $dbh = C4::Context->dbh; my @where_strs = ('field_id = ?'); my @where_args = ($self->{id}); if ($record_id) { push @where_strs, 'record_id = ?'; push @where_args, $record_id; } my $query = q{ DELETE FROM additional_field_values WHERE } . join (' AND ', @where_strs); $dbh->do($query, undef, @where_args); } sub all { my ( $class, $args ) = @_; die "BAD CALL: Don't use fetch_all_values as an instance method" if ref $class and UNIVERSAL::can($class,'can'); my $tablename = $args->{tablename}; my $searchable = $args->{searchable}; my $dbh = C4::Context->dbh; my $query = q| SELECT * FROM additional_fields WHERE 1 |; $query .= q| AND tablename = ?| if $tablename; $query .= q| AND searchable = ?| if defined $searchable; my $results = $dbh->selectall_arrayref( $query, {Slice => {}}, ( $tablename ? $tablename : (), defined $searchable ? $searchable : () ) ); my @fields; for my $r ( @$results ) { push @fields, Koha::AdditionalField->new({ id => $r->{id}, tablename => $r->{tablename}, name => $r->{name}, authorised_value_category => $r->{authorised_value_category}, marcfield => $r->{marcfield}, searchable => $r->{searchable}, }); } return \@fields; } sub fetch_all_values { my ( $class, $args ) = @_; die "BAD CALL: Don't use fetch_all_values as an instance method" if ref $class and UNIVERSAL::can($class,'can'); my $record_id = $args->{record_id}; my $tablename = $args->{tablename}; return unless $tablename; my $dbh = C4::Context->dbh; my $values = $dbh->selectall_arrayref( q| SELECT afv.record_id, af.name, afv.value FROM additional_fields af, additional_field_values afv WHERE af.id = afv.field_id AND af.tablename = ? | . ( $record_id ? q| AND afv.record_id = ?| : q|| ), {Slice => {}}, ( $tablename, ($record_id ? $record_id : ()) ) ); my $r; for my $v ( @$values ) { $r->{$v->{record_id}}{$v->{name}} = $v->{value}; } return $r; } sub get_matching_record_ids { my ( $class, $args ) = @_; die "BAD CALL: Don't use fetch_all_values as an instance method" if ref $class and UNIVERSAL::can($class,'can'); my $fields = $args->{fields} // []; my $tablename = $args->{tablename}; my $exact_match = $args->{exact_match} // 1; return [] unless @$fields; my $dbh = C4::Context->dbh; my $query = q|SELECT * FROM |; my ( @subqueries, @args ); my $i = 0; for my $field ( @$fields ) { $i++; my $subquery = qq|( SELECT record_id, field$i.name AS field${i}_name FROM additional_field_values afv LEFT JOIN ( SELECT afv.id, af.name, afv.value FROM additional_field_values afv, additional_fields af WHERE afv.field_id = af.id AND af.name = ? AND af.tablename = ? AND value LIKE ? ) AS field$i USING (id) WHERE field$i.id IS NOT NULL ) AS values$i |; $subquery .= ' USING (record_id)' if $i > 1; push @subqueries, $subquery; push @args, $field->{name}, $tablename, ( ( $exact_match or $field->{authorised_value_category} ) ? $field->{value} : "%$field->{value}%" ); } $query .= join( ' LEFT JOIN ', @subqueries ) . ' WHERE 1'; for my $j ( 1 .. $i ) { $query .= qq| AND field${j}_name IS NOT NULL|; } my $values = $dbh->selectall_arrayref( $query, {Slice => {}}, @args ); return [ map { $_->{record_id} } @$values ] } 1; __END__ =head1 NAME Koha::AdditionalField =head1 SYNOPSIS use Koha::AdditionalField; my $af1 = Koha::AdditionalField->new({id => $id}); my $af2 = Koha::AuthorisedValue->new({ tablename => 'my_table', name => 'a_name', authorised_value_category => 'LOST', marcfield => '200$a', searchable => 1, }); $av1->delete; $av2->{name} = 'another_name'; $av2->update; =head1 DESCRIPTION Class for managing additional fields into Koha. =head1 METHODS =head2 new Create a new Koha::AdditionalField object. This method can be called using several ways. Either with the id for existing field or with different values for a new one. =over 4 =item B The caller just knows the id of the additional field and want to retrieve all values. =item B The caller wants to create a new additional field. =back =head2 fetch The information will be retrieved from the database. =head2 update If the AdditionalField object has been modified and the values have to be modified into the database, call this method. =head2 delete Remove a the record in the database using the id the object. =head2 insert Insert a new AdditionalField object into the database. =head2 insert_values Insert new values for a record. my $af = Koha::AdditionalField({ id => $id })->fetch; my $af->{values} = { record_id1 => 'my value', record_id2 => 'another value', }; $af->insert_values; =head2 fetch_values Retrieve values from the database for a given record_id. The record_id argument is optional. my $af = Koha::AdditionalField({ id => $id })->fetch; my $values = $af->fetch_values({record_id => $record_id}); $values will be equal to something like: { record_id => { field_name1 => 'value1', field_name2 => 'value2', } } =head2 delete_values Delete values from the database for a given record_id. The record_id argument is optional. my $af = Koha::AdditionalField({ id => $id })->fetch; $af->delete_values({record_id => $record_id}); =head2 all Retrieve all additional fields in the database given some parameters. Parameters are optional. This method returns a list of AdditionalField objects. This is a static method. my $fields = Koha::AdditionalField->all; or my $fields = Koha::AdditionalField->all{(tablename => 'my_table'}); or my $fields = Koha::AdditionalField->all({searchable => 1}); =head2 fetch_all_values Retrieve all values for a table name. This is a static method. my $values = Koha::AdditionalField({ tablename => 'my_table' }); $values will be equel to something like: { record_id1 => { field_name1 => 'value1', field_name2 => 'value2', }, record_id2 => { field_name1 => 'value3', field_name2 => 'value4', } } =head2 get_matching_record_ids Retrieve all record_ids for records matching the field values given in parameter. This method returns a list of ids. This is a static method. my $fields = [ { name => 'field_name', value => 'field_value', } ]; my $ids = Koha::AdditionalField->get_matching_record_ids( { tablename => 'subscription', fields => $fields } ); =head1 AUTHOR Jonathan Druart =head1 COPYRIGHT Copyright 2013 BibLibre =head1 LICENSE This file is part of Koha. Koha is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Koha is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Koha; if not, see .