Bugzilla – Attachment 156265 Details for
Bug 31383
Additional contents: We need a parent and child table
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 31383: Create a parent-child DB relation for additional content
Bug-31383-Create-a-parent-child-DB-relation-for-ad.patch (text/plain), 52.33 KB, created by
Martin Renvoize (ashimema)
on 2023-09-27 10:01:17 UTC
(
hide
)
Description:
Bug 31383: Create a parent-child DB relation for additional content
Filename:
MIME Type:
Creator:
Martin Renvoize (ashimema)
Created:
2023-09-27 10:01:17 UTC
Size:
52.33 KB
patch
obsolete
>From 116b1b092315291bbc25d18a04d6300498602d8d Mon Sep 17 00:00:00 2001 >From: Jonathan Druart <jonathan.druart@bugs.koha-community.org> >Date: Mon, 27 Feb 2023 21:47:59 +0100 >Subject: [PATCH] Bug 31383: Create a parent-child DB relation for additional > content > >In the design of additional contents the idea of a parent-child relation is implicitly present. You have a default page and translations. >But we do this in one table coming from the old news items. > >Several reports show that we would be better off creating a parent table listing the main news items, CMS pages or HTML content. And a child table containing the title, content and lang. > >Note that this first step is a prelimenary step to clean this area and make it more robust and extensible. More enhancements to come. > >What is this patchset doing? >* DB changes >- Rename additional_contents.idnew with id >- Create a new table additional_contents_localizations(id, additional_content_id, title, content, lang) that will contain the translated contents >- Move the content to this new table >- Remove title, content and lang columns from additional_contents >- Replace the notice templates that are using ''<news>" (should only be ISSUESLIP) and remove support for this syntax. Also add a warning in case other occurrences of uses of the old syntax exist. > >* CRUD >- We add a new Koha::AdditionalContentsLocalization[s] couple, and move some logic from Koha::AdditionalContent[s] to there. Note that, to prevent too much drastic changes in notice templates, and to make them easy to use, the different attributes of the content object is accessible from the translated content object (ie. Koha::AdditionalContentsLocatlization->library is available and return $self->additional_content->library). I think it's an elegant way to keep things simple. >- No changes expected for "NewsLog" logging >- Little behaviour changes for pages, see tools/page.pl changes. We are now passing the id of the content, and the desired language, instead of the mix of "page_id" or code and lang. Note that here we certainly need to rename "language" query param to not change the full interface language. > >Test plan: >0. Preparation steps, use master > a. Create notice templates that are using "<< additional_contents.code >>". This won't be replaced, but we want the update process to alert us. > b. Create several news, additional contents, pages. Some with translated contents, some without. > c. Make sure ISSUESLIP has the "<news>" section. If you are using the sample data there is nothing to do here > d. Turn on NewsLogs >1. Apply the patches, restart_all, updatedatabase >=> Confirm that the new table is created and filled with the contents you had prior to the update >=> Confirm that additional_contents_localizations.updated_on has been kept to the previous values >=> Confirm that ISSUESLIP has been replaced properly >=> Confirm that you get a warning about the additional_contents >2. Create, update, delete news, html customs, pages >=> Confirm that the additional_contents_localizations.updated_on is only adjusted when required >=> Confirm that the logs are correctly created when NewsLogs is on >3. Check some items out, generate a slip >=> Confirm that the news are displayed at the bottom of the slip, and that the publication date is correctly formatted >4. Have several HTML customizations (like OpacNav, opacheader), in translated in different languages >=> Confirm that the default values is displayed when you are using the interface in a language without translation >=> Confirm that the translated version is picked when it exists > >Notes for QA: >* I am not sure we really need the alert during the update DB process about the additional_contents leftover. We should not have them outside of ISSUESLIP. >Shouldn't it hurt? >* There is something ugly in sample_news.yml, the id is hardcoded. But how do we prevent that and keep translatability? > >Sponsored-by: Rijksmuseum, Netherlands >Signed-off-by: Marcel de Rooy <m.de.rooy@rijksmuseum.nl> >Signed-off-by: Martin Renvoize <martin.renvoize@ptfs-europe.com> >--- > C4/Letters.pm | 10 +- > C4/Members.pm | 24 +- > Koha/AdditionalContent.pm | 64 +++++- > Koha/AdditionalContents.pm | 61 ++--- > Koha/AdditionalContentsLocalization.pm | 217 ++++++++++++++++++ > Koha/AdditionalContentsLocalizations.pm | 52 +++++ > .../prog/en/modules/intranet-main.tt | 6 +- > .../en/modules/tools/additional-contents.tt | 37 +-- > .../prog/en/modules/tools/page.tt | 2 +- > .../bootstrap/en/modules/opac-main.tt | 2 +- > .../bootstrap/en/modules/opac-news-rss.tt | 2 +- > .../bootstrap/en/modules/opac-page.tt | 4 +- > opac/opac-main.pl | 1 - > opac/opac-page.pl | 20 +- > tools/additional-contents.pl | 205 ++++++++--------- > tools/page.pl | 24 +- > 16 files changed, 517 insertions(+), 214 deletions(-) > create mode 100644 Koha/AdditionalContentsLocalization.pm > create mode 100644 Koha/AdditionalContentsLocalizations.pm > >diff --git a/C4/Letters.pm b/C4/Letters.pm >index b2ad4c2d1d2..6d207d97daf 100644 >--- a/C4/Letters.pm >+++ b/C4/Letters.pm >@@ -762,7 +762,7 @@ sub _parseletter_sth { > ($table eq 'subscription') ? "SELECT * FROM $table WHERE subscriptionid = ?" : > ($table eq 'serial') ? "SELECT * FROM $table WHERE serialid = ?" : > ($table eq 'problem_reports') ? "SELECT * FROM $table WHERE reportid = ?" : >- ($table eq 'additional_contents' || $table eq 'opac_news') ? "SELECT * FROM additional_contents WHERE idnew = ?" : >+ ($table eq 'additional_contents' || $table eq 'opac_news') ? "SELECT * FROM additional_contents_localizations WHERE id = ?" : > ($table eq 'recalls') ? "SELECT * FROM $table WHERE recall_id = ?" : > undef ; > unless ($query) { >@@ -1733,16 +1733,16 @@ sub _get_tt_params { > pk => 'itemnumber', > }, > additional_contents => { >- module => 'Koha::AdditionalContents', >+ module => 'Koha::AdditionalContentsLocalizations', > singular => 'additional_content', > plural => 'additional_contents', >- pk => 'idnew', >+ pk => 'id', > }, > opac_news => { >- module => 'Koha::AdditionalContents', >+ module => 'Koha::AdditionalContentsLocalizations', > singular => 'news', > plural => 'news', >- pk => 'idnew', >+ pk => 'id', > }, > aqorders => { > module => 'Koha::Acquisition::Orders', >diff --git a/C4/Members.pm b/C4/Members.pm >index 919f6c38908..3db8c7fa9c8 100644 >--- a/C4/Members.pm >+++ b/C4/Members.pm >@@ -516,40 +516,24 @@ sub IssueSlip { > issues => $all, > }; > } >- my $news = Koha::AdditionalContents->search_for_display( >+ my @news_ids = Koha::AdditionalContents->search_for_display( > { > category => 'news', > location => 'slip', > lang => $patron->lang, > library_id => $branch, > } >- ); >- my @news; >- while ( my $n = $news->next ) { >- my $all = $n->unblessed_all_relateds; >- >- # FIXME We keep newdate and timestamp for backward compatibility (from GetNewsToDisplay) >- # But we should remove them and adjust the existing templates in a db rev >- # FIXME This must be formatted in the notice template >- my $published_on_dt = output_pref({ dt => dt_from_string( $all->{published_on} ), dateonly => 1 }); >- $all->{newdate} = $published_on_dt; >- $all->{timestamp} = $published_on_dt; >- >- push @news, { >- additional_contents => $all, >- }; >- } >+ )->get_column('id'); > $letter_code = 'ISSUESLIP'; > %repeat = ( > checkedout => \@checkouts, > overdue => \@overdues, >- news => \@news, > ); > %loops = ( > issues => [ map { $_->{issues}{itemnumber} } @checkouts ], > overdues => [ map { $_->{issues}{itemnumber} } @overdues ], >- opac_news => [ map { $_->{additional_contents}{idnew} } @news ], >- additional_contents => [ map { $_->{additional_contents}{idnew} } @news ], >+ opac_news => \@news_ids, >+ additional_contents => \@news_ids, > ); > } > >diff --git a/Koha/AdditionalContent.pm b/Koha/AdditionalContent.pm >index c0c321458f3..3aca46ad875 100644 >--- a/Koha/AdditionalContent.pm >+++ b/Koha/AdditionalContent.pm >@@ -19,11 +19,11 @@ package Koha::AdditionalContent; > > use Modern::Perl; > >- > use Koha::Database; > use Koha::DateUtils qw( dt_from_string ); > use Koha::Libraries; > use Koha::Patrons; >+use Koha::AdditionalContentsLocalizations; > > use base qw(Koha::Object); > >@@ -61,7 +61,7 @@ Returns 1 if the additional content is expired or 0; > =cut > > sub is_expired { >- my ( $self ) = @_; >+ my ($self) = @_; > > return 0 unless $self->expirationdate; > return 1 if dt_from_string( $self->expirationdate ) < dt_from_string->truncate( to => 'day' ); >@@ -77,13 +77,69 @@ Returns Koha::Library object or undef > =cut > > sub library { >- my ( $self ) = @_; >+ my ($self) = @_; > > my $library_rs = $self->_result->branchcode; > return unless $library_rs; >- return Koha::Library->_new_from_dbic( $library_rs ); >+ return Koha::Library->_new_from_dbic($library_rs); >+} >+ >+=head3 translated_contents >+ >+my $translated_contents = $additional_content->translated_contents; >+$additional_content->translated_contents(\@contents) >+ >+=cut >+ >+sub translated_contents { >+ my ( $self, $localizations ) = @_; >+ if ($localizations) { >+ my $schema = $self->_result->result_source->schema; >+ $schema->txn_do( >+ sub { >+ $self->translated_contents->delete; >+ >+ for my $localization (@$localizations) { >+ $self->_result->add_to_additional_contents_localizations($localization); >+ } >+ } >+ ); >+ } >+ >+ my $rs = $self->_result->additional_contents_localizations; >+ return Koha::AdditionalContentsLocalizations->_new_from_dbic($rs); > } > >+=head3 default_localization >+ >+my $default_content = $additional_content->default_localization; >+ >+Return the default content. >+ >+=cut >+ >+sub default_localization { >+ my ($self) = @_; >+ my $rs = $self->_result->additional_contents_localizations->find( { lang => 'default' } ); >+ return Koha::AdditionalContentsLocalization->_new_from_dbic($rs); >+} >+ >+=head3 translated_content >+ >+my $translated_content = $additional_content->translated_content($lang); >+ >+Return the translated content for a given language. The default is returned if none exist. >+ >+=cut >+ >+sub translated_content { >+ my ( $self, $lang ) = @_; >+ my $content = $self->translated_contents->search( >+ { lang => [ 'default', ( $lang ? $lang : () ) ] }, >+ { ( $lang ? ( order_by => \[ "field(lang, '" . $lang . "', 'default')" ] ) : () ) } >+ )->next; >+ return $content; >+} > > =head3 _type > >diff --git a/Koha/AdditionalContents.pm b/Koha/AdditionalContents.pm >index 430ff539346..cd3b00b8968 100644 >--- a/Koha/AdditionalContents.pm >+++ b/Koha/AdditionalContents.pm >@@ -19,9 +19,12 @@ package Koha::AdditionalContents; > > use Modern::Perl; > >+use Array::Utils qw( array_minus ); >+ > use Koha::Database; > use Koha::Exceptions; > use Koha::AdditionalContent; >+use Koha::AdditionalContentsLocalizations; > > use base qw(Koha::Objects); > >@@ -72,44 +75,42 @@ sub search_for_display { > my ( $self, $params ) = @_; > > my $search_params; >- $search_params->{location} = $params->{location}; >- $search_params->{branchcode} = $params->{library_id} ? [ $params->{library_id}, undef ] : undef; >+ $search_params->{location} = $params->{location}; >+ $search_params->{branchcode} = $params->{library_id} ? [ $params->{library_id}, undef ] : undef; > $search_params->{published_on} = { '<=' => \'CAST(NOW() AS DATE)' }; >- $search_params->{-or} = [ expirationdate => { '>=' => \'CAST(NOW() AS DATE)' }, >- expirationdate => undef ]; >+ $search_params->{-or} = [ >+ expirationdate => { '>=' => \'CAST(NOW() AS DATE)' }, >+ expirationdate => undef >+ ]; > $search_params->{category} = $params->{category} if $params->{category}; > >+ my $contents = $self->SUPER::search( $search_params, { order_by => 'number' } ); >+ > if ( $params->{lang} ) { >- # FIXME I am failing to translate the following query >- # SELECT a1.category, a1.code, COALESCE(a2.title, a1.title) >- # FROM additional_contents a1 >- # LEFT JOIN additional_contents a2 on a1.code=a2.code AND a2.lang="es-ES" >- # WHERE a1.lang = 'default'; >- >- # So we are retrieving the code with a translated content, then the other ones >- my $translated_contents = >- $self->SUPER::search( { %$search_params, lang => $params->{lang} } ); >- my $default_contents = $self->SUPER::search( >+ my $translated_contents = Koha::AdditionalContentsLocalizations->search( > { >- %$search_params, >- lang => 'default', >- code => >- { '-not_in' => [ $translated_contents->get_column('code') ] } >+ additional_content_id => [$contents->get_column('id')], >+ lang => $params->{lang}, > } > ); >- >- return $self->SUPER::search( >+ my @all_content_id = $contents->get_column('id'); >+ my @translated_content_id = $translated_contents->get_column('additional_content_id'); >+ my $default_contents = Koha::AdditionalContentsLocalizations->search( >+ { >+ additional_content_id => [array_minus(@all_content_id, @translated_content_id)], >+ lang => 'default', >+ } >+ ); >+ return Koha::AdditionalContentsLocalizations->search( > { >- idnew => [ >- $translated_contents->get_column('idnew'), >- $default_contents->get_column('idnew') >+ id => [ >+ $translated_contents->get_column('id'), >+ $default_contents->get_column('id'), > ] > }, >- { order_by => 'number' } > ); > } >- >- return $self->SUPER::search({%$search_params, lang => 'default'}, { order_by => 'number'}); >+ return $contents->search( { lang => 'default' }, { order_by => 'number' } )->translated_contents; > } > > =head3 find_best_match >@@ -129,13 +130,17 @@ sub find_best_match { > my $library_id = $params->{library_id}; > my $lang = $params->{lang}; > >- my $rs = $self->SUPER::search({ >+ my $contents = $self->SUPER::search({ > category => $params->{category}, > location => $params->{location}, >- lang => [ $lang, 'default' ], > branchcode => [ $library_id, undef ], > }); > >+ my $rs = Koha::AdditionalContentsLocalizations->search({ >+ additional_content_id => [ $contents->get_column('id') ], >+ lang => [ $lang, 'default' ], >+ }); >+ > # Pick the best > my ( $alt1, $alt2, $alt3 ); > while( my $rec = $rs->next ) { >diff --git a/Koha/AdditionalContentsLocalization.pm b/Koha/AdditionalContentsLocalization.pm >new file mode 100644 >index 00000000000..82bd961c2ac >--- /dev/null >+++ b/Koha/AdditionalContentsLocalization.pm >@@ -0,0 +1,217 @@ >+package Koha::AdditionalContentsLocalization; >+ >+# 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 <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use Koha::Database; >+use Koha::AdditionalContents; >+ >+use base qw(Koha::Object); >+ >+=head1 NAME >+ >+Koha::AdditionalContentsLocalization - Koha Additional content localization object class >+ >+=head1 API >+ >+=head2 Class Methods >+ >+=cut >+ >+=head3 additional_content >+ >+ $c->additional_content; >+ >+Return the Koha::AdditionalContent for this translated content. >+ >+=cut >+ >+sub additional_content { >+ my ( $self ) = @_; >+ my $rs = $self->_result->additional_content; >+ return Koha::AdditionalContent->_new_from_dbic($rs); >+} >+ >+=head3 author >+ >+ $c->author; >+ >+Return the author of the content >+ >+=cut >+ >+sub author { >+ my ( $self, @params ) = @_; >+ return $self->additional_content->author(@params); >+} >+ >+=head3 is_expired >+ >+ $c->is_expired; >+ >+Return $content->is_expired >+ >+=cut >+ >+sub is_expired { >+ my ( $self, @params ) = @_; >+ return $self->additional_content->is_expired(@params); >+} >+ >+=head3 library >+ >+ $c->library; >+ >+Return the library of the content >+ >+=cut >+ >+sub library { >+ my ( $self, @params ) = @_; >+ return $self->additional_content->library(@params); >+} >+ >+=head3 category >+ >+ $c->category; >+ >+Return the category of the content >+ >+=cut >+ >+sub category { >+ my ( $self, @params ) = @_; >+ return $self->additional_content->category; >+} >+ >+=head3 code >+ >+ $c->code; >+ >+Return the code of the content >+ >+=cut >+ >+sub code { >+ my ( $self, @params ) = @_; >+ return $self->additional_content->code(@params); >+} >+ >+=head3 location >+ >+ $c->location; >+ >+Return the location of the content >+ >+=cut >+ >+sub location { >+ my ( $self, @params ) = @_; >+ return $self->additional_content->location(@params); >+} >+ >+=head3 branchcode >+ >+ $c->branchcode; >+ >+Return the branchcode of the content >+ >+=cut >+ >+sub branchcode { >+ my ( $self, @params ) = @_; >+ return $self->additional_content->branchcode(@params); >+} >+ >+=head3 published_on >+ >+ $c->published_on; >+ >+Return the publication date of the content >+ >+=cut >+ >+sub published_on { >+ my ( $self, @params ) = @_; >+ return $self->additional_content->published_on(@params); >+} >+ >+=head3 updated_on >+ >+ $c->updated_on; >+ >+Return the date of the last update of the content >+ >+=cut >+ >+sub updated_on { >+ my ( $self, @params ) = @_; >+ return $self->additional_content->updated_on(@params); >+} >+ >+=head3 expirationdate >+ >+ $c->expirationdate; >+ >+Return the expiration date of the content >+ >+=cut >+ >+sub expirationdate { >+ my ( $self, @params ) = @_; >+ return $self->additional_content->expirationdate(@params); >+} >+ >+=head3 number >+ >+ $c->number; >+ >+Return the number (order of display) of the content >+ >+=cut >+ >+sub number { >+ my ( $self, @params ) = @_; >+ return $self->additional_content->number(@params); >+} >+ >+=head3 borrowernumber >+ >+ $c->borrowernumber; >+ >+Return the borrowernumber of the content >+ >+=cut >+ >+sub borrowernumber { >+ my ( $self, @params ) = @_; >+ return $self->additional_content->borrowernumber(@params); >+} >+ >+=head2 Class Methods >+ >+=cut >+ >+=head3 _type >+ >+=cut >+ >+sub _type { >+ return 'AdditionalContentsLocalization'; >+} >+ >+1; >diff --git a/Koha/AdditionalContentsLocalizations.pm b/Koha/AdditionalContentsLocalizations.pm >new file mode 100644 >index 00000000000..80d2cb90b88 >--- /dev/null >+++ b/Koha/AdditionalContentsLocalizations.pm >@@ -0,0 +1,52 @@ >+package Koha::AdditionalContentsLocalizations; >+ >+# 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 <http://www.gnu.org/licenses>. >+ >+use Modern::Perl; >+ >+use Koha::Database; >+use Koha::Exceptions; >+use Koha::AdditionalContentsLocalization; >+ >+use base qw(Koha::Objects); >+ >+=head1 NAME >+ >+Koha::AdditionalContentLocalizations - Koha Additional content localization object set class >+ >+=head1 API >+ >+=head2 Class Methods >+ >+=cut >+ >+=head3 _type >+ >+=cut >+ >+sub _type { >+ return 'AdditionalContentsLocalization'; >+} >+ >+=head3 object_class >+ >+=cut >+ >+sub object_class { >+ return 'Koha::AdditionalContentsLocalization'; >+} >+ >+1; >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt >index 1b4dfe93dd6..841a56d6213 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/intranet-main.tt >@@ -29,12 +29,12 @@ > <h3><span class="news_title">News</span></h3> > [% SET show_author = Koha.Preference('NewsAuthorDisplay') == 'staff' || Koha.Preference('NewsAuthorDisplay') == 'both' %] > [% FOREACH koha_new IN koha_news %] >- <div class="newsitem" id="news[% koha_new.idnew | html %]"><h4>[% koha_new.title | html %]</h4> >+ <div class="newsitem" id="news[% koha_new.additional_content_id | html %]"><h4>[% koha_new.title | html %]</h4> > <div class="newsbody">[% koha_new.content | $raw %]</div> > <p class="newsfooter"> Posted on [% koha_new.published_on | $KohaDates %][% IF( show_author && koha_new.author ) %] by <span class="newsauthor">[% INCLUDE 'patron-title.inc' patron=koha_new.author %]<br />[% END %] > [% IF ( CAN_user_tools_edit_additional_contents ) %] >- <a href="/cgi-bin/koha/tools/additional-contents.pl?op=add_form&id=[% koha_new.idnew | uri %]">Edit</a> >- | <a class="news_delete" href="/cgi-bin/koha/tools/additional-contents.pl?op=delete_confirmed&ids=[% koha_new.idnew | html %]">Delete</a> >+ <a href="/cgi-bin/koha/tools/additional-contents.pl?op=add_form&id=[% koha_new.additional_content_id | uri %]">Edit</a> >+ | <a class="news_delete" href="/cgi-bin/koha/tools/additional-contents.pl?op=delete_confirmed&ids=[% koha_new.additional_content_id | html %]">Delete</a> > | <a href="/cgi-bin/koha/tools/additional-contents.pl?op=add_form">New</a> > [% END %] > </p> >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/additional-contents.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/additional-contents.tt >index dbf97f69f08..970bb853c2e 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/additional-contents.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/additional-contents.tt >@@ -59,7 +59,7 @@ > [% END %] > [% END %] > [% WRAPPER breadcrumb_item bc_active= 1 %] >- [% IF additional_content.idnew %] >+ [% IF additional_content.id %] > <span>Modify additional content</span> > [% ELSE %] > <span>Add additional content</span> >@@ -205,7 +205,7 @@ > <input type="hidden" name="op" value="add_validate" /> > <input type="hidden" name="category" value="[% category | html %]" /> > <input type="hidden" name="code" value="[% additional_content.code | html %]" /> >- <input type="hidden" name="idnew" value="[% additional_content.idnew | html %]" /> >+ <input type="hidden" name="id" value="[% additional_content.id | html %]" /> > <input type="hidden" id="redirect" name="redirect" value="" /> > <input type="hidden" id="editmode" name="editmode" value="[% editmode | html %]" /> > <fieldset class="rows"> >@@ -280,16 +280,18 @@ > > [% WRAPPER tab_panels %] > [% FOR language IN languages %] >+ [% SET translated_content = translated_contents.item(language.lang) %] > [% WRAPPER tab_panel tabname="lang_${language.lang}" %] > <fieldset> > <ol> > <li> > <label for="title_[% language.lang | html %]">Title: </label> >- <input id="title_[% language.lang| html %]" size="100" maxlength="250" type="text" name="title_[% language.lang | html %]" value="[% translated_contents.item(language.lang).title | html %]"> >+ <input id="title_[% language.lang| html %]" size="100" maxlength="250" type="text" name="title_[% language.lang | html %]" value="[% translated_content.title | html %]"> > </li> > <li> > <label for="content_[% language.lang | html %]">Content: </label> >- <textarea name="content_[% language.lang | html %]" id="content_[% language.lang | html %]" data-lang="[% language.lang | html%]" cols="75" rows="10">[% translated_contents.item(language.lang).content | html %]</textarea> >+ <textarea name="content_[% language.lang | html %]" id="content_[% language.lang | html %]" data-lang="[% language.lang | html%]" cols="75" rows="10">[% translated_content.content | html %]</textarea> >+ <input type="hidden" name="id_[% language.lang | html %]" value="[% translated_content.id | html %]" /> > <input type="hidden" name="lang" value="[% language.lang | html %]" /> > </li> > </ol> >@@ -364,9 +366,10 @@ > </thead> > <tbody> > [% FOREACH c IN additional_contents%] >+ [% SET default_localization = c.default_localization %] > [% IF ( c.is_expired ) %]<tr class="expired">[% ELSE %]<tr>[% END %] > <td> >- <input type="checkbox" name="ids" value="[% c.idnew | html %]" /> >+ <input type="checkbox" name="ids" value="[% c.id | html %]" /> > </td> > <td> > [% IF c.category == 'news' || c.category == 'pages' %] >@@ -389,22 +392,22 @@ > <td>[% c.number | html %]</td> > <td data-order="[% c.published_on | html %]">[% c.published_on | $KohaDates %]</td> > <td data-order="[% c.expirationdate | html %]">[% c.expirationdate | $KohaDates %] [% IF ( c.is_expired ) %](<span class="expired">expired</span>)[% END %]</td> >- <td>[% c.title | html %]</td> >+ <td>[% default_localization.title | html %]</td> > <td>[% IF ( c.author) %][% INCLUDE 'patron-title.inc' patron=c.author %][% END %]</td> > [% IF category == 'pages' %] > <td class="actions"> > [% IF c.location == 'opac_only' OR c.location == 'staff_and_opac' %] > <strong>OPAC</strong>: >- <a target="_blank" href="[% Koha.Preference('OPACBaseURL') | url %]/cgi-bin/koha/opac-page.pl?page_id=[% c.idnew | url %]" title="View on OPAC">Default</a> >+ <a target="_blank" href="[% Koha.Preference('OPACBaseURL') | url %]/cgi-bin/koha/opac-page.pl?page_id=[% c.id | uri %]&lang=default" title="View on OPAC">Default</a> > OR >- <a target="_blank" href="[% Koha.Preference('OPACBaseURL') | url %]/cgi-bin/koha/opac-page.pl?code=[% c.code | url %]" title="View on OPAC">Current language</a> >+ <a target="_blank" href="[% Koha.Preference('OPACBaseURL') | url %]/cgi-bin/koha/opac-page.pl?page_id=[% c.id | uri %]&lang=[% lang | uri %]" title="View on OPAC">Current language</a> > [% END %] > [% IF c.location == 'staff_only' OR c.location == 'staff_and_opac' %] > [% IF c.location == 'staff_and_opac' %]<br/>[% END %] > <strong>Staff interface</strong>: >- <a href="/cgi-bin/koha/tools/page.pl?page_id=[% c.idnew | url %]" title="View on staff interface">Default</a> >+ <a href="/cgi-bin/koha/tools/page.pl?page_id=[% c.id | uri %]&lang=default" title="View on staff interface">Default</a> > OR >- <a href="/cgi-bin/koha/tools/page.pl?code=[% c.code | url %]" title="View on staff interface">Current language</a> >+ <a href="/cgi-bin/koha/tools/page.pl?page_id=[% c.id | uri %]&lang=[% lang | uri %]" title="View on staff interface">Current language</a> > [% END %] > </td> > [% END %] >@@ -416,10 +419,10 @@ > <div class="modal-dialog" role="document"> > <div class="modal-content modal-lg"> > <div class="modal-header"> >- <h5 class="modal-title">Preview of: "[% c.title | html %]"</h5> >+ <h5 class="modal-title">Preview of: "[% default_localization.title | html %]"</h5> > </div> > <div class="modal-body"> >- [% c.content | $raw %] >+ [% default_localization.content | $raw %] > </div> > <div class="modal-footer"> > <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> >@@ -429,21 +432,21 @@ > </td> > <td class="actions"> > <div class="btn-group dropup"> >- <a href="/cgi-bin/koha/tools/additional-contents.pl?op=add_form&id=[% c.idnew | uri %]&editmode=[% editmode | uri %]" class="btn btn-default btn-xs"> <i class="fa-solid fa-pencil" aria-hidden="true"></i> Edit</a><button class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown"> >+ <a href="/cgi-bin/koha/tools/additional-contents.pl?op=add_form&id=[% c.id | uri %]&editmode=[% editmode | uri %]" class="btn btn-default btn-xs"> <i class="fa-solid fa-pencil"></i> Edit</a><button class="btn btn-default btn-xs dropdown-toggle" data-toggle="dropdown"> > <span class="caret"></span> > </button> > <ul class="dropdown-menu pull-right"> > <li> > [% IF ( wysiwyg ) %] >- <a href="/cgi-bin/koha/tools/additional-contents.pl?op=add_form&id=[% c.idnew | uri %]&editmode=text"><i class="fa-solid fa-pencil" aria-hidden="true"></i> Edit with text editor</a> >+ <a href="/cgi-bin/koha/tools/additional-contents.pl?op=add_form&id=[% c.id | uri %]&editmode=text"><i class="fa-solid fa-pencil"></i> Edit with text editor</a> > [% ELSE %] >- <a href="/cgi-bin/koha/tools/additional-contents.pl?op=add_form&id=[% c.idnew | uri %]&editmode=wysiwyg"><i class="fa-solid fa-pencil" aria-hidden="true"></i> Edit with WYSIWYG editor</a> >+ <a href="/cgi-bin/koha/tools/additional-contents.pl?op=add_form&id=[% c.id | uri %]&editmode=wysiwyg"><i class="fa-solid fa-pencil"></i> Edit with WYSIWYG editor</a> > [% END %] > </li> > </ul> > </div> > <div class="btn-group"> >- <a href="#" class="delete_news btn btn-default btn-xs" data-idnew="[% c.idnew | html %]"><i class="fa fa-trash-can"></i> Delete</a> >+ <a href="#" class="delete_news btn btn-default btn-xs" data-idnew="[% c.id | html %]"><i class="fa fa-trash-can"></i> Delete</a> > </div> > </td> > </tr> >@@ -580,7 +583,7 @@ > $("#del_form").on("click", ".delete_news", function(e){ > e.preventDefault(); > if( confirmDelete( _("Are you sure you want to delete this content? This cannot be undone.") ) ){ >- $("#del_ids").val( $(this).data("idnew") ); >+ $("#del_ids").val( $(this).data("id") ); > $("#delete_single").submit(); > } > }); >diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/page.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/page.tt >index 634ce415a48..bac75f8e07a 100644 >--- a/koha-tmpl/intranet-tmpl/prog/en/modules/tools/page.tt >+++ b/koha-tmpl/intranet-tmpl/prog/en/modules/tools/page.tt >@@ -6,7 +6,7 @@ > [% INCLUDE 'doc-head-close.inc' %] > </head> > >-<body id="tools_page_[% page.idnew | html %]" class="tools"> >+<body id="tools_page_[% page.additional_content_id | html %]" class="tools"> > [% WRAPPER 'header.inc' %] > [% INCLUDE 'cat-search.inc' %] > [% END %] >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-main.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-main.tt >index 482e3bd98bd..bc541e0f9a1 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-main.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-main.tt >@@ -102,7 +102,7 @@ > [% IF ( news_item ) %] > [% koha_new.title | html %] > [% ELSE %] >- <a name="newsitem[% koha_new.idnew | html %]" href="/cgi-bin/koha/opac-main.pl?news_id=[% koha_new.idnew | uri %]">[% koha_new.title | html %]</a> >+ <a name="newsitem[% koha_new.id | html %]" href="/cgi-bin/koha/opac-main.pl?news_id=[% koha_new.id | uri %]">[% koha_new.title | html %]</a> > [% END %] > </h4> > <div class="newsbody">[% koha_new.content | $raw %]</div> >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-news-rss.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-news-rss.tt >index 645ba47e0f3..8654ace1412 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-news-rss.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-news-rss.tt >@@ -10,7 +10,7 @@ > <item> > <title>[% newsitem.title | html %]</title> > <description>[% newsitem.content | $raw %]</description> >- <guid>[% OPACBaseURL | html %]/cgi-bin/koha/opac-main.pl#newsitem[% newsitem.idnew | html %]</guid> >+ <guid>[% OPACBaseURL | html %]/cgi-bin/koha/opac-main.pl#newsitem[% newsitem.additional_content_id | html %]</guid> > </item> > [% END %] > </channel> >diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-page.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-page.tt >index 5b4742da93b..ed5f55c3c39 100644 >--- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-page.tt >+++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-page.tt >@@ -9,7 +9,7 @@ > [% INCLUDE 'doc-head-close.inc' %] > [% BLOCK cssinclude %][% END %] > </head> >-[% INCLUDE 'bodytag.inc' bodyid='opac-page-' _ page.idnew %] >+[% INCLUDE 'bodytag.inc' bodyid='opac-page-' _ page.additional_content_id %] > [% INCLUDE 'masthead.inc' %] > > <div class="main"> >@@ -44,7 +44,7 @@ > [% END %] > > [% IF page %] >- <div class="maincontent"> >+ <div id="page_[% page.additional_content_id | html %]" class="maincontent"> > <h1>[% page.title | html %]</h1> > > <div class="page_content"> >diff --git a/opac/opac-main.pl b/opac/opac-main.pl >index f90d98cdcfd..9cc772a25e8 100755 >--- a/opac/opac-main.pl >+++ b/opac/opac-main.pl >@@ -27,7 +27,6 @@ use C4::Members; > use C4::Overdues qw( checkoverdues ); > use Koha::Checkouts; > use Koha::Holds; >-use Koha::AdditionalContents; > use Koha::Patron::Messages; > > my $input = CGI->new; >diff --git a/opac/opac-page.pl b/opac/opac-page.pl >index cba09dddfda..5854160dbba 100755 >--- a/opac/opac-page.pl >+++ b/opac/opac-page.pl >@@ -20,6 +20,7 @@ use Modern::Perl; > use CGI qw ( -utf8 ); > use C4::Auth qw( get_template_and_user ); > use C4::Output qw( output_html_with_http_headers ); >+use C4::Languages qw( getlanguage ); > use Koha::AdditionalContents; > > my $query = CGI->new(); >@@ -34,21 +35,22 @@ my ( $template, $borrowernumber, $cookie ) = get_template_and_user( > ); > > my $page_id = $query->param('page_id'); >-my $code = $query->param('code'); >-my $page; >+my $lang = $query->param('language'); > > my $homebranch = $ENV{OPAC_BRANCH_DEFAULT}; > if (C4::Context->userenv) { > $homebranch = C4::Context->userenv->{'branch'}; > } > >-if( $page_id ) { >- $page = Koha::AdditionalContents->search({ idnew => $page_id, location => ['opac_only', 'staff_and_opac'], branchcode => [ $homebranch, undef ] }); >-} elsif( $code ) { >- my $lang = $query->param('language') || $query->cookie('KohaOpacLanguage') || $template->lang; >- # In the next query we make sure that the 'default' records come after the regular languages >- $page = Koha::AdditionalContents->search({ code => $code, lang => ['default', $lang], location => ['opac_only', 'staff_and_opac'], branchcode => [ $homebranch, undef ] }, { order_by => { -desc => \[ 'CASE WHEN lang="default" THEN "" ELSE lang END' ]}} ); >+my $page = Koha::AdditionalContents->find($page_id); >+ >+if ( !$page || $page->category ne 'pages' || $page->branchcode && $page->branchcode != $homebranch || $page->location ne 'opac_only' && $page->location ne 'staff_and_opac' ) { >+ print $query->redirect('/cgi-bin/koha/errors/404.pl'); >+ exit; > } >-$template->param( $page && $page->count ? ( page => $page->next ) : ( page_error => 1 ) ); >+ >+my $content = $page->translated_content( $lang || C4::Languages::getlanguage($query) ); >+ >+$template->param( page => $content ); > > output_html_with_http_headers $query, $cookie, $template->output; >diff --git a/tools/additional-contents.pl b/tools/additional-contents.pl >index e066bb8fee9..75c32ca9c36 100755 >--- a/tools/additional-contents.pl >+++ b/tools/additional-contents.pl >@@ -24,6 +24,8 @@ > > use Modern::Perl; > use CGI qw ( -utf8 ); >+use Try::Tiny; >+use Array::Utils qw( array_minus ); > use C4::Auth qw(get_template_and_user); > use C4::Koha; > use C4::Context; >@@ -65,18 +67,9 @@ if ( $op eq 'add_form' ) { > > my $additional_content = Koha::AdditionalContents->find($id); > my $translated_contents; >- if ( $additional_content ) { >- $translated_contents = { >- map { $_->lang => $_ } Koha::AdditionalContents->search( >- { >- category => $additional_content->category, >- code => $additional_content->code, >- location => $additional_content->location, >- branchcode => $additional_content->branchcode, >- } >- )->as_list >- }; >- $category = $additional_content->category; >+ if ($additional_content) { >+ $translated_contents = { map { $_->lang => $_ } $additional_content->translated_contents->as_list }; >+ $category = $additional_content->category; > } > $template->param( > additional_content => $additional_content, >@@ -88,7 +81,6 @@ elsif ( $op eq 'add_validate' ) { > my $location = $cgi->param('location'); > my $code = $cgi->param('code'); > my $branchcode = $cgi->param('branchcode') || undef; >- my $idnew = $cgi->param('idnew'); > > my @lang = $cgi->multi_param('lang'); > >@@ -96,101 +88,92 @@ elsif ( $op eq 'add_validate' ) { > my $published_on = $cgi->param('published_on'); > my $number = $cgi->param('number'); > >- my $original_default = $idnew ? Koha::AdditionalContents->find($idnew) : undef; >- >- my $success = 1; >- for my $lang ( sort {$a ne 'default'} @lang ) { # Process 'default' first >- my $title = $cgi->param( 'title_' . $lang ); >- my $content = $cgi->param( 'content_' . $lang ); >- # Force a default record >- $content ||= '<!-- no_content -->' if $lang eq 'default'; >- >- my $additional_content = Koha::AdditionalContents->find( >- { >- category => $category, >- code => $code, >- branchcode => $original_default ? $original_default->branchcode : $branchcode, >- lang => $lang, >- } >- ); >- # Delete if title or content is empty >- if( $lang ne 'default' && !$title && !$content ) { >- if ( $additional_content ) { >- eval { $additional_content->delete }; >- unless ($@) { >- logaction('NEWS', 'DELETE' , undef, sprintf("%s|%s|%s|%s", $additional_content->code, $additional_content->title, $additional_content->lang, $additional_content->content)); >- } >- } >- next; >- } elsif ( $additional_content ) { >- my $updated; >- eval { >- $additional_content->set( >- { >- category => $category, >- code => $code, >+ try { >+ Koha::Database->new->schema->txn_do( >+ sub { >+ my $additional_content; >+ my $params = { > location => $location, > branchcode => $branchcode, >- title => $title, >- content => $content, >- lang => $lang, > expirationdate => $expirationdate, > published_on => $published_on, > number => $number, > borrowernumber => $borrowernumber, >- } >- ); >- $updated = $additional_content->_result->get_dirty_columns; >- $additional_content->store; >- $id = $additional_content->idnew; >- }; >- if ($@) { >- $success = 0; >- push @messages, { type => 'error', code => 'error_on_update' }; >- last; >- } >+ }; > >- logaction('NEWS', 'MODIFY' , undef, sprintf("%s|%s|%s|%s", $code, $title, $lang, $content)) >- if C4::Context->preference("NewsLog") && $updated; >- } >- else { >- my $additional_content = Koha::AdditionalContent->new( >- { >- category => $category, >- code => $code || 'tmp_code', >- location => $location, >- branchcode => $branchcode, >- title => $title, >- content => $content, >- lang => $lang, >- expirationdate => $expirationdate, >- published_on => $published_on, >- number => $number, >- borrowernumber => $borrowernumber, >+ if ( $id ) { >+ $additional_content = Koha::AdditionalContents->find($id); >+ $additional_content->set($params)->store; >+ } else { >+ $additional_content = Koha::AdditionalContent->new( >+ { >+ category => $category, >+ code => $code, >+ branchcode => $branchcode, >+ %$params, >+ } >+ )->store; > } >- )->store; >- eval { >- $additional_content->store; > unless ($code) { > $additional_content->discard_changes; >- $code = $category eq 'news' >- ? 'News_' . $additional_content->idnew >- : $location . '_' . $additional_content->idnew; >+ $code = >+ $category eq 'news' >+ ? 'News_' . $additional_content->id >+ : $location . '_' . $additional_content->id; > $additional_content->code($code)->store; >- $id = $additional_content->idnew; >+ $id = $additional_content->id; > } >- }; >- if ($@) { >- $success = 0; >- push @messages, { type => 'error', code => 'error_on_insert' }; >- last; >- } >+ my @translated_contents; >+ my $existing_contents = $additional_content->translated_contents; >+ my @seen_ids; >+ for my $lang (@lang) { >+ my $id = $cgi->param( 'id_' . $lang ); >+ my $title = $cgi->param( 'title_' . $lang ); >+ my $content = $cgi->param( 'content_' . $lang ); >+ $content ||= '<!-- no_content -->' if $lang eq 'default'; > >- logaction('NEWS', 'ADD' , undef, sprintf("%s|%s|%s|%s", $code, $title, $lang, $content)) >- if C4::Context->preference("NewsLog"); >- } >+ next unless $title || $content; > >- } >+ push @seen_ids, $id; >+ push @translated_contents, >+ { >+ title => $title, >+ content => $content, >+ lang => $lang, >+ }; >+ >+ if ( C4::Context->preference("NewsLog") ) { >+ my $existing_content = $existing_contents->find($id); >+ if ( $existing_content ) { >+ if ( $existing_content->title ne $title || $existing_content->content ne $content ) { >+ logaction('NEWS', 'MODIFY' , undef, sprintf("%s|%s|%s|%s", $code, $title, $lang, $content)); >+ } >+ } else { >+ logaction('NEWS', 'ADD' , undef, sprintf("%s|%s|%s|%s", $code, $title, $lang, $content)) >+ } >+ } >+ } >+ >+ if ( C4::Context->preference("NewsLog") ) { >+ my @existing_ids = $existing_contents->get_column('id'); >+ my @deleted_ids = array_minus( @existing_ids, @seen_ids ); >+ for my $id ( @deleted_ids ) { >+ my $c = $existing_contents->find($id); >+ logaction('NEWS', 'DELETE' , undef, sprintf("%s|%s|%s", $code, $c->lang, $c->content)); >+ } >+ } >+ >+ $additional_content->translated_contents( \@translated_contents ); >+ } >+ ); >+ } catch { >+ warn $_; >+ if ( $id ) { >+ push @messages, { type => 'error', code => 'error_on_update' }; >+ } else { >+ push @messages, { type => 'error', code => 'error_on_insert' }; >+ } >+ }; > > if( $redirect eq "just_save" ){ > print $cgi->redirect("/cgi-bin/koha/tools/additional-contents.pl?op=add_form&id=$id&category=$category&editmode=$editmode&redirect=done"); >@@ -202,38 +185,37 @@ elsif ( $op eq 'add_validate' ) { > elsif ( $op eq 'delete_confirmed' ) { > output_and_exit_if_error($cgi, $cookie, $template, { check => 'csrf_token' }); > my @ids = $cgi->multi_param('ids'); >- my $deleted = eval { > >- my $schema = Koha::Database->new->schema; >- $schema->txn_do( >+ try { >+ Koha::Database->new->schema->txn_do( > sub { > my $contents = >- Koha::AdditionalContents->search( { idnew => \@ids } ); >+ Koha::AdditionalContents->search( { id => \@ids } ); > >- while ( my $c = $contents->next ) { >- Koha::AdditionalContents->search( { code => $c->code } )->delete; >- if ( C4::Context->preference("NewsLog") ) { >- logaction('NEWS', 'DELETE' , undef, sprintf("%s|%s|%s|%s", $c->code, $c->title, $c->lang, $c->content)); >+ if ( C4::Context->preference("NewsLog") ) { >+ while ( my $c = $contents->next ) { >+ my $translated_contents = $c->translated_contents; >+ while ( my $translated_content = $translated_contents->next ) { >+ logaction('NEWS', 'DELETE' , undef, sprintf("%s|%s|%s|%s", $c->code, $translated_content->lang, $translated_content->content)); >+ } > } > } >+ $contents->delete; > } > ); >- }; >- >- if ( $@ or not $deleted ) { >- push @messages, { type => 'error', code => 'error_on_delete' }; >- } >- else { > push @messages, { type => 'message', code => 'success_on_delete' }; >- } >+ } catch { >+ warn $_; >+ push @messages, { type => 'error', code => 'error_on_delete' }; >+ }; > > $op = 'list'; > } > > if ( $op eq 'list' ) { > my $additional_contents = Koha::AdditionalContents->search( >- { category => $category, lang => 'default' }, >- { order_by => { -desc => 'published_on' } } >+ { category => $category, 'additional_contents_localizations.lang' => 'default' }, >+ { order_by => { -desc => 'published_on' }, join => 'additional_contents_localizations' } > ); > $template->param( additional_contents => $additional_contents ); > } >@@ -269,6 +251,7 @@ $template->param( > wysiwyg => $wysiwyg, > editmode => $editmode, > languages => \@languages, >+ messages => \@messages, > ); > > output_html_with_http_headers $cgi, $cookie, $template->output; >diff --git a/tools/page.pl b/tools/page.pl >index b504bdb6f85..d30288a6d0f 100755 >--- a/tools/page.pl >+++ b/tools/page.pl >@@ -32,18 +32,20 @@ my ( $template, $loggedinuser, $cookie ) = get_template_and_user( > } > ); > >-my $branch = C4::Context->userenv->{'branch'}; > my $page_id = $query->param('page_id'); >-my $code = $query->param('code'); >-my $page; >- >-if( $page_id ) { >- $page = Koha::AdditionalContents->search({ idnew => $page_id, location => ['staff_only', 'staff_and_opac'], branchcode => [ $branch, undef ] }); >-} elsif( $code ) { >- my $lang = $query->param('language') || $query->cookie('KohaOpacLanguage'); >- # In the next query we make sure that the 'default' records come after the regular languages >- $page = Koha::AdditionalContents->search({ code => $code, lang => ['default', $lang], location => ['staff_only', 'staff_and_opac'], branchcode => [ $branch, undef ] }, { order_by => { -desc => \[ 'CASE WHEN lang="default" THEN "" ELSE lang END' ]}} ); >+my $lang = $query->param('language'); >+ >+my $branch = C4::Context->userenv->{'branch'}; >+ >+my $page = Koha::AdditionalContents->find($page_id); >+ >+if ( !$page || $page->category ne 'pages' || $page->branchcode && $page->branchcode != $branch || $page->location ne 'staff_only' && $page->location ne 'staff_and_opac' ) { >+ print $query->redirect('/cgi-bin/koha/errors/404.pl'); >+ exit; > } >-$template->param( $page && $page->count ? ( page => $page->next ) : ( page_error => 1 ) ); >+ >+my $content = $page->translated_content( $lang || C4::Languages::getlanguage($query) ); >+ >+$template->param( page => $content ); > > output_html_with_http_headers $query, $cookie, $template->output; >-- >2.41.0
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 31383
:
147891
|
147892
|
147893
|
147894
|
147895
|
147896
|
149813
|
149814
|
149815
|
149816
|
149817
|
149818
|
152423
|
152424
|
152425
|
152426
|
152427
|
152428
|
152545
|
152546
|
152547
|
152566
|
152660
|
152661
|
152662
|
152663
|
152664
|
152665
|
152666
|
152667
|
152668
|
152669
|
153013
|
153666
|
153667
|
153668
|
153669
|
153670
|
153671
|
153672
|
153673
|
153674
|
153675
|
153676
|
156048
|
156049
|
156050
|
156051
|
156052
|
156053
|
156054
|
156055
|
156056
|
156057
|
156058
|
156265
|
156266
|
156267
|
156268
|
156269
|
156270
|
156271
|
156272
|
156273
|
156274
|
156275
|
156276
|
157539
|
157540
|
157541
|
157542
|
157543
|
157544
|
157545
|
157546
|
157547
|
157548
|
157549
|
157550
|
157580
|
157585
|
157640
|
157741
|
157742