From 20bf72e34d4147be3d503085827f3aa859fa0a98 Mon Sep 17 00:00:00 2001 From: Hammat Wele Date: Fri, 2 Aug 2024 18:16:55 +0000 Subject: [PATCH] Bug 17385: (QA follow-up) Add CustomXSLTExportPath & improve descriptions Here is a summary the corrections : - Addressed all warnings and failures identified by the QA testing tool - Revised the description of the export format (Removed all instances of 'XSL - ') - Updated the description of the custom option in the OpacExportOptions system preference - Corrected the MARC21_simple_export.xsl file to generate a valid HTML file - Introduced the new preference system CustomXSLTExportPath, allowing users to choose the path for the custom XSL files - Updated the sysprefs.sql file for OpacExportOptions and CustomXSLTExportPath - Added a new atomic update file for OpacExportOptions and CustomXSLTExportPath - Updated XSLT tests (t/db_dependent/XSLT.t) NEW TEST PLAN Prerequisites: - Have more than one record in your catalog Test steps: 1) Search for a record in the intranet 2) Click on the 'Save' button and observe the dropdown menu ---> There is no 'Simple Export' in the dropdown menu 3) Apply the patch 4) In 'Koha administration > System preferences' search 'OpacExportOptions' 5) Enable 'Simple HTML formats' and click on 'Save all OPAC preferences' 6) Repeat steps 1 and 2 ---> There is now 'Simple Export' option in the dropdown menu 7) Click on 'Simple Export' ---> a .html file should be downloaded ---> you should see the record informations in the downloaded file 8) Add some item to your Cart 9) Open your Cart 10) Click on the 'Download' button, then click on 'Simple Export' ---> a .html file should be downloaded ---> you should see the records informations in the downloaded file 11) Add some items to a list 12) Open the list 13) Click on the 'Download list' button, then click on 'Simple Export' ---> a .html file should be downloaded ---> you should see the records informations in the downloaded file 14) Do the same steps in OPAC (steps 6 to 13) 15) On your computer, create a folder that will contain the xsl files in the attachment 16 [review]) In the intranet, go to 'Koha administration > System preferences' and search for 'CustomXSLTExportPath' 17) Write the full path to your created folder and click on the 'Save all Cataloging preferences' 18) Repeat steps 6 to 14 (no need to download this time, only check that 'Simple Export 1' and 'Simple Export 2' are displaying when you click on the 'Save'/'Download'/'Download list' button) 19) In the system preferences search for OpacExportOptions and disable 'Simple HTML formats' 20) Repeat steps 6 to 13 in OPAC ---> Notice that 'Simple Export 1' and 'Simple Export 2' are not in the menu anymore 21) Run 'prove t/db_dependent/XSLT.t' Signed-off-by: David Nind --- C4/XSLT.pm | 42 +++++-- ...ustomOptionForOpacExportOptions_syspref.pl | 29 +++++ installer/data/mysql/mandatory/sysprefs.sql | 3 +- .../prog/en/includes/cat-toolbar.inc | 2 +- .../en/includes/virtualshelves-toolbar.inc | 2 +- .../admin/preferences/cataloguing.pref | 5 + .../en/modules/admin/preferences/opac.pref | 2 +- .../prog/en/modules/basket/basket.tt | 2 +- .../prog/en/modules/catalogue/detail.tt | 2 +- .../modules/virtualshelves/downloadshelf.tt | 2 +- .../biblioexport/MARC21_simple_export.xsl | 119 ++++++++++-------- .../en/includes/opac-detail-sidebar.inc | 2 +- .../bootstrap/en/modules/opac-basket.tt | 2 +- .../bootstrap/en/modules/opac-downloadcart.tt | 2 +- .../en/modules/opac-downloadshelf.tt | 2 +- .../bootstrap/en/modules/opac-shelves.tt | 2 +- t/db_dependent/XSLT.t | 87 +++++++------ 17 files changed, 197 insertions(+), 110 deletions(-) create mode 100755 installer/data/mysql/atomicupdate/bug_17385-CustomOptionForOpacExportOptions_syspref.pl diff --git a/C4/XSLT.pm b/C4/XSLT.pm index 34df696a1e..3af1d13b49 100644 --- a/C4/XSLT.pm +++ b/C4/XSLT.pm @@ -37,7 +37,6 @@ use XML::LibXML; use Encode; use vars qw(@ISA @EXPORT); - my $engine; #XSLT Handler object our (@ISA, @EXPORT_OK); @@ -129,26 +128,39 @@ sub get_xslt_sysprefs { return $sysxml; } +=head2 get_xsl_filename + + return xsl filenames in CustomXSLTExportPath or in /koha-tmpl/intranet-tmpl/prog/en/xslt/biblioexport/ + +=cut + sub get_xsl_filename { my ( $xslsyspref, $xslfilename ) = @_; my $lang = C4::Languages::getlanguage(); $xslfilename ||= C4::Context->preference($xslsyspref) || "default"; + my $customXSLTExportPath = C4::Context->preference('CustomXSLTExportPath'); if ($xslsyspref eq "XSLTCustomExport") { my $dir; - $dir = C4::Context->config('intrahtdocs') . - '/' . C4::Context->preference("template") . - '/' . $lang . - '/xslt/biblioexport'; + $dir = + $customXSLTExportPath + ? $customXSLTExportPath + : C4::Context->config('intrahtdocs') . '/' + . C4::Context->preference("template") . '/' + . $lang + . '/xslt/biblioexport'; $xslfilename = $dir . "/" . $xslfilename; } elsif ($xslsyspref eq "OPACXSLTCustomExport") { my $dir; - $dir = C4::Context->config('opachtdocs') . - '/' . C4::Context->preference("opacthemes") . - '/' . $lang . - '/xslt/biblioexport'; + $dir = + $customXSLTExportPath + ? $customXSLTExportPath + : C4::Context->config('opachtdocs') . '/' + . C4::Context->preference("opacthemes") . '/' + . $lang + . '/xslt/biblioexport'; $xslfilename = $dir . "/" . $xslfilename; } elsif ( $xslfilename =~ /^\s*"?default"?\s*$/i ) { @@ -425,6 +437,7 @@ sub CustomXSLTExportList { my $opac = shift; # opac (1) vs intranet (0) return [] if $opac && C4::Context->preference('OpacExportOptions') !~ /custom/; + my $customXSLTExportPath = C4::Context->preference('CustomXSLTExportPath'); # Check the cache first my $cache = Koha::Caches->get_instance; my $key = $opac ? 'CustomXSLTExportListOPAC' : 'CustomXSLTExportListIntra'; @@ -433,10 +446,13 @@ sub CustomXSLTExportList { my @tabFiles; - my $dir = C4::Context->config( $opac ? 'opachtdocs' : 'intrahtdocs') . - '/' . C4::Context->preference( $opac ? "opacthemes" : "template") . - '/' . C4::Languages::getlanguage() . - '/xslt/biblioexport'; + my $dir = + $customXSLTExportPath + ? $customXSLTExportPath + : C4::Context->config( $opac ? 'opachtdocs' : 'intrahtdocs' ) . '/' + . C4::Context->preference( $opac ? "opacthemes" : "template" ) . '/' + . C4::Languages::getlanguage() + . '/xslt/biblioexport'; my @files = glob qq("$dir/*.xsl"); foreach my $file (@files) { if ( -f "$file" ) { diff --git a/installer/data/mysql/atomicupdate/bug_17385-CustomOptionForOpacExportOptions_syspref.pl b/installer/data/mysql/atomicupdate/bug_17385-CustomOptionForOpacExportOptions_syspref.pl new file mode 100755 index 0000000000..75323b10b8 --- /dev/null +++ b/installer/data/mysql/atomicupdate/bug_17385-CustomOptionForOpacExportOptions_syspref.pl @@ -0,0 +1,29 @@ +use Modern::Perl; + +return { + bug_number => "17385", + description => "Add a custom option for OpacExportOptions system preference", + up => sub { + my ($args) = @_; + my ( $dbh, $out ) = @$args{qw(dbh out)}; + + $dbh->do( + q{ + UPDATE systempreferences + SET value = 'bibtex,dc,marcxml,marc8,utf8,marcstd,mods,ris,isbd,custom' + WHERE variable = 'OpacExportOptions'; + } + ); + + $dbh->do( + q{ + INSERT IGNORE INTO systempreferences (variable,value,options,explanation,type) + VALUES ('CustomXSLTExportPath','','','The path to the folder containing the customized XSL files for export',''); + } + ); + + # sysprefs + say $out "Updated system preference 'OpacExportOptions'"; + say $out "Added new system preference 'OpacCustomExportFilePath'"; + }, +}; \ No newline at end of file diff --git a/installer/data/mysql/mandatory/sysprefs.sql b/installer/data/mysql/mandatory/sysprefs.sql index 1a7cd033e9..ba06bb061d 100644 --- a/installer/data/mysql/mandatory/sysprefs.sql +++ b/installer/data/mysql/mandatory/sysprefs.sql @@ -183,6 +183,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('CurrencyFormat','US','US|FR|CH','Determines the display format of currencies. eg: \'36000\' is displayed as \'360 000,00\' in \'FR\' or \'360,000.00\' in \'US\'.','Choice'), ('CustomCoverImages','0',NULL,'If enabled, the custom cover images will be displayed in the staff interface. CustomCoverImagesURL must be defined.','YesNo'), ('CustomCoverImagesURL','',NULL,'Define an URL serving book cover images, using the following patterns: %issn%, %isbn%, FIXME ADD MORE (use it with CustomCoverImages and/or OPACCustomCoverImages)','free'), +('CustomXSLTExportPath','','','The path to the folder containing the customized XSL files for export',''), ('dateformat','us','metric|us|iso|dmydot','Define global date format (us mm/dd/yyyy, metric dd/mm/yyy, ISO yyyy-mm-dd, dmydot dd.mm.yyyy)','Choice'), ('DebugLevel','2','0|1|2','Define the level of debugging information sent to the browser when errors are encountered (set to 0 in production). 0=none, 1=some, 2=most','Choice'), ('decreaseLoanHighHolds','0','','Decreases the loan period for items with number of holds above the threshold specified in decreaseLoanHighHoldsValue','YesNo'), @@ -479,7 +480,7 @@ INSERT INTO systempreferences ( `variable`, `value`, `options`, `explanation`, ` ('OPACDetailQRCode','0','','Enable the display of a QR Code on the OPAC detail page','YesNo'), ('OPACdidyoumean','',NULL,'Did you mean? configuration for the OPAC. Do not change, as this is controlled by /cgi-bin/koha/admin/didyoumean.pl.','Free'), ('OPACDisplay856uAsImage','OFF','OFF|Details|Results|Both','Display the URI in the 856u field as an image, the corresponding OPACXSLT option must be on','Choice'), -('OpacExportOptions','bibtex,dc,marcxml,marc8,utf8,marcstd,mods,ris,isbd','','Define export options available on OPAC detail page.','multiple'), +('OpacExportOptions','bibtex,dc,marcxml,marc8,utf8,marcstd,mods,ris,isbd,custom','','Define export options available on OPAC detail page.','multiple'), ('OPACFallback', 'prog', 'bootstrap|prog', 'Define the fallback theme for the OPAC interface.', 'Themes'), ('OpacFavicon','','','Enter a complete URL to an image to replace the default Koha favicon on the OPAC','free'), ('OPACFineNoRenewals','100','','Fine limit above which user cannot renew books via OPAC','Integer'), diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc index 9ce7a2b155..361154bf4e 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/cat-toolbar.inc @@ -156,7 +156,7 @@
  • MODS (XML)
  • RIS
  • [% FOREACH filesOption IN filesOptions %] -
  • XSL - [% filesOption.filename | html %]
  • +
  • [% filesOption.filename | html %]
  • [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/includes/virtualshelves-toolbar.inc b/koha-tmpl/intranet-tmpl/prog/en/includes/virtualshelves-toolbar.inc index a5e475eb8a..88477e4f53 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/includes/virtualshelves-toolbar.inc +++ b/koha-tmpl/intranet-tmpl/prog/en/includes/virtualshelves-toolbar.inc @@ -37,7 +37,7 @@
  • CSV - [% csv_profile.profile | html %]
  • [% END %] [% FOREACH xsl_export IN xsl_exports %] -
  • XSL - [% xsl_export.filename | html %]
  • +
  • [% xsl_export.filename | html %]
  • [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref index ffd9b7e549..346c05618b 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/cataloguing.pref @@ -384,6 +384,11 @@ Cataloging: - "All values of repeating tags and subfields will be printed with the given BibTeX tag." - "
    " - "Use '@' ( with quotes ) as the BT_TAG to replace the bibtex record type with a field value of your choosing." + - + - "Use this" + - pref: CustomXSLTExportPath + class: long + - "as the path containing the customized XSL files for export (write the complete path)." - - "Include the following fields when exporting RIS:" - pref: RisExportAdditionalFields diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref index b35ced247b..23abb31d6c 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/preferences/opac.pref @@ -296,7 +296,7 @@ OPAC: mods: MODS ris: RIS isbd: ISBD - custom: XSL - Simple Export + custom: Simple HTML formats - - pref: OpacSeparateHoldings choices: diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tt index 13734eb561..5bb426b8dd 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/basket/basket.tt @@ -65,7 +65,7 @@
  • CSV - [% csv_profile.profile | html %]
  • [% END %] [% FOREACH xsl_export IN xsl_exports %] -
  • XSL - [% xsl_export.filename | html %]
  • +
  • [% xsl_export.filename | html %]
  • [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt index cd88c9b2a9..656d2c51c5 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/catalogue/detail.tt @@ -870,7 +870,7 @@ [% FOREACH filesOption IN filesOptions %] - + [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/downloadshelf.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/downloadshelf.tt index db6e1674b9..640e573c49 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/downloadshelf.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/virtualshelves/downloadshelf.tt @@ -43,7 +43,7 @@ [% END %] [% FOREACH xsl_export IN xsl_exports %] - + [% END %] diff --git a/koha-tmpl/intranet-tmpl/prog/en/xslt/biblioexport/MARC21_simple_export.xsl b/koha-tmpl/intranet-tmpl/prog/en/xslt/biblioexport/MARC21_simple_export.xsl index faad19d521..a4b082cc24 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/xslt/biblioexport/MARC21_simple_export.xsl +++ b/koha-tmpl/intranet-tmpl/prog/en/xslt/biblioexport/MARC21_simple_export.xsl @@ -1,62 +1,81 @@ - + + + + - + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:marc="http://www.loc.gov/MARC21/slim" + exclude-result-prefixes="marc" + title="Simple Export"> + - + <!DOCTYPE html> + + + + + Simple Export + + + + + -

    - - - - - - - - - - - - - - -
    - - - - - - - +

    + + + + + + + + + + + + - - - + +
    + + + + + + + + + + + + +
    - -
    - -
    - - - - - - - - - - - + +
    + + + + + + + + + + + + + + +
    -
    -
    -

    +

    diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-detail-sidebar.inc b/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-detail-sidebar.inc index 670ff9fc6e..5b3d9464a7 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-detail-sidebar.inc +++ b/koha-tmpl/opac-tmpl/bootstrap/en/includes/opac-detail-sidebar.inc @@ -85,7 +85,7 @@ [% ELSE %] [% FOREACH filesOption IN filesOptions %] - XSL - [% filesOption.filename | html %] + [% filesOption.filename | html %] [% END %] [% END %] [% END %] diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-basket.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-basket.tt index 881a86bbe7..3771273c51 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-basket.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-basket.tt @@ -44,7 +44,7 @@ [% FOREACH option IN export_options %] [% IF option == 'custom' %] [% FOREACH xsl_export IN xsl_exports %] - XSL - [% xsl_export.filename | html %] + [% xsl_export.filename | html %] [% END %] [% END %] [% END %] diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadcart.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadcart.tt index 58e2bfdfb3..7cf2988d93 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadcart.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadcart.tt @@ -21,7 +21,7 @@ [% END %] [% FOREACH xsl_export IN xsl_exports %] - + [% END %]
    diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadshelf.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadshelf.tt index 93108b2535..56946d1052 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadshelf.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-downloadshelf.tt @@ -69,7 +69,7 @@ [% END %] [% FOREACH xsl_export IN xsl_exports %] - + [% END %] Required diff --git a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-shelves.tt b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-shelves.tt index 64f0c3184d..a90508e0e6 100644 --- a/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-shelves.tt +++ b/koha-tmpl/opac-tmpl/bootstrap/en/modules/opac-shelves.tt @@ -247,7 +247,7 @@ [% FOREACH option IN export_options %] [% IF option == 'custom' %] [% FOREACH xsl_export IN xsl_exports %] - XSL - [% xsl_export.filename | html %] + [% xsl_export.filename | html %] [% END %] [% END %] [% END %] diff --git a/t/db_dependent/XSLT.t b/t/db_dependent/XSLT.t index 5ee1c8d333..7121f8cf8d 100755 --- a/t/db_dependent/XSLT.t +++ b/t/db_dependent/XSLT.t @@ -38,7 +38,7 @@ my $builder = t::lib::TestBuilder->new; our $cache = Koha::Caches->get_instance; subtest 'Tests moved from t' => sub { - plan tests => 11; + plan tests => 14; $schema->storage->txn_begin; my $dir = File::Temp->newdir(); @@ -76,40 +76,57 @@ subtest 'Tests moved from t' => sub { is(find_and_slurp($dir, 'nope', 'fr-FR'), 'Theme prog, language en', 'Fell back to prog/en for nope/fr-FR'); my $matching_string = q{[0|1]}; - my $sysprefs_xml = C4::XSLT::get_xslt_sysprefs(); - ok( $sysprefs_xml =~ m/$matching_string/, 'singleBranchMode has no value'); - - t::lib::Mocks::mock_config('opachtdocs', "$dir"); - make_path("$dir/bootstrap/en/xslt/biblioexport"); - - # Make XSL with title - open my $fh, '>', "$dir/bootstrap/en/xslt/biblioexport/export_01.xsl"; - print $fh qq| - - |; - close $fh; - - # Make XSL without title - open $fh, '>', "$dir/bootstrap/en/xslt/biblioexport/export_02.xsl"; - print $fh qq| - - |; - close $fh; - - open $fh, '>', "$dir/bootstrap/en/xslt/biblioexport/export_03.xsl"; - print $fh qq||; - close $fh; - - t::lib::Mocks::mock_preference( 'OpacExportOptions', 'custom'); - my @custom_xslts = @{C4::XSLT::CustomXSLTExportList(1)}; - ok((scalar @custom_xslts) == 2, "CustomXSLTExportList finds custom XSLTs"); - ok($custom_xslts[0]->{filename} eq "Export 01", "Title is specified in root node"); - ok($custom_xslts[1]->{filename} eq "export_02", "Title is filename if not specified"); + my $sysprefs_xml = C4::XSLT::get_xslt_sysprefs(); + ok( $sysprefs_xml =~ m/$matching_string/, 'singleBranchMode has no value' ); + + sub createXSLTFiles { + my ( $path ) = @_; + + open my $fh, '>', "$path/export_01.xsl"; + print $fh qq| + + |; + close $fh; + + # Make XSL without title + open $fh, '>', "$path/export_02.xsl"; + print $fh qq| + + |; + close $fh; + + open $fh, '>', "$path/export_03.xsl"; + print $fh qq||; + close $fh; + } + + t::lib::Mocks::mock_preference( 'CustomXSLTExportPath', '' ); + t::lib::Mocks::mock_config( 'opachtdocs', "$dir" ); + + make_path( "$dir/bootstrap/" . C4::Languages::getlanguage() . "/xslt/biblioexport" ); + createXSLTFiles( "$dir/bootstrap/" . C4::Languages::getlanguage() . "/xslt/biblioexport" ); + + t::lib::Mocks::mock_preference( 'OpacExportOptions', 'custom' ); + my @custom_xslts = @{ C4::XSLT::CustomXSLTExportList(1) }; + + ok( ( scalar @custom_xslts ) == 2, "CustomXSLTExportList finds custom XSLTs" ); + ok( $custom_xslts[0]->{filename} eq "Export 01", "Title is specified in root node" ); + ok( $custom_xslts[1]->{filename} eq "export_02", "Title is filename if not specified" ); + + # CustomXSLTExportPath + t::lib::Mocks::mock_preference( 'CustomXSLTExportPath', "/$dir/XSLTExportFiles" ); + make_path("$dir/XSLTExportFiles"); + createXSLTFiles("$dir/XSLTExportFiles"); + @custom_xslts = @{ C4::XSLT::CustomXSLTExportList(1) }; + + ok( ( scalar @custom_xslts ) == 2, "CustomXSLTExportList finds custom XSLTs with CustomXSLTExportPath" ); + ok( $custom_xslts[0]->{filename} eq "Export 01", "Title is specified in root node with CustomXSLTExportPath" ); + ok( $custom_xslts[1]->{filename} eq "export_02", "Title is filename if not specified with CustomXSLTExportPath" ); $schema->storage->txn_rollback; }; -- 2.39.2