**New Developers Working Group** ====== The Perl Logic Layer ====== ===== Structure ===== Most of Evergreen's business logic can be found in perl modules. In the git repository, these can be found at Open-ILS/src/perlmods/lib. Perl modules typically have the .pm file extension. Evergreen's business logic is tested by the tests in Open-ILS/src/perlmods/t (which do not require the concerto data set to be running in the database) and Open-ILS/src/perlmods/live_t (which do). Perl tests have the .t file extension. The perl code is also exercised indirectly by the end-to-end tests for the Angular staff client. There are many Perl scripts throughout the project. Perl scripts generally have the .pl file extension. ===== Dependencies ===== Evergreen's Perl code relies on many packages from CPAN. They are installed by your operating system's package manager and cpan itself when you run the Open-ILS/src/extras/Makefile.install Makefile. When you need to add or remove a dependency, do so for all of the operating systems listed in the Open-ILS/src/extras/install directory. ===== Checking your work ===== Here are some things you can do to check your work while working with Evergreen's perl code: * If it is in an OpenSRF method: Build it, install it, and restart your services. Then call the method (through the UI, or directly using the srfsh). Confirm that the behavior is what you expected. * To build and install the perl code, you can run ''make'' as opensrf then ''make install'' as root. Alternatively, you can build and install the perl code in a single step with ''cd Open-ILS/src/perlmods && ./Build install'' as root. * Write some tests to confirm that your code is working as intended, without any unintended side effects. * Run ''perl -cw [name of file]'' to check your syntax and check for warnings. * Run perlcritic on your code to check for common gotchas and readability. You can paste your code directly into [[http://perlcritic.com/|the online PerlCritic checker]] or install the command line tool from CPAN. This is not a requirement (most perl code in Evergreen violates these rules), but it can be very instructive. * Temporarily adding print or logging statements to your work. If you'd like to print an array or hash, try using Data::Dumper. ===== Using Cstore to interact with the database ===== A lot of the Perl code uses a Cstore editor to create, retrieve, update, delete, and search records in the database. The following examples are loosely based on the Carousel Perl module: use strict; use warnings; use OpenILS::Utils::CStoreEditor qw/:funcs/; use OpenILS::Utils::Fieldmapper; ######### # Setup # ######### # Create a new Cstore editor my $e = new_editor(authtoken => $auth); # Check that the auth token is valid return $e->event unless $e->checkauth; # Check that the user has the ADMIN_CAROUSEL permission. # CStore doesn't perform any permission checks by itself, # so your Perl code needs to explicity do these checks. return $e->event unless $e->allowed('ADMIN_CAROUSEL'); ######################### # Create a new carousel # ######################### # Assemble a new fieldmapper object in memory my $carousel = Fieldmapper::container::carousel->new; $carousel->name('My carousel'); $carousel->type(1); $carousel->owner($e->requestor->ws_ou); $carousel->creator($e->requestor->id); $carousel->editor($e->requestor->id); $carousel->max_items(12); $carousel->bucket(30); # Then, start a transaction in the database. This is # required any time you are changing data in the database $e->xact_begin; # Persist the carousel to the database $e->create_container_carousel($carousel) or return $e->event; # Commit the transaction. It's a best practice to not leave # transactions open for a long time. $e->xact_commit or return $e->event; ############################# # Retrieve a carousel by ID # ############################# my $other_carousel = $e->retrieve_container_carousel(3); # Retrieve by id: 3 print "The other carousel name is $other_carousel->name"; ##################### # Update a carousel # ##################### # Again, make our changes in memory $carousel->bucket(40); # Open a transaction, persist our change to the database, and commit the transaction $e->xact_begin; $e->update_container_carousel($carousel) or return $e->event; $e->xact_commit or return $e->event; ##################### # Delete a carousel # ##################### # Similarly, open a transaction, call the delete method, and commit the transaction. # Note that the delete_container_carousel method accepts a Fieldmapper object, rather # than just an ID. So, if you only have an ID, you'll need to retrieve the object # from the database before you can delete it. $e->xact_begin; $e->delete_container_carousel($carousel) or return $e->event; $e->xact_commit or return $e->event; #################################### # Search carousels by field values # #################################### # No transaction needed, since we aren't making changes my $carousels_with_bucket_forty = $e->search_container_carousel( { bucket => 30 }); # The search_* methods return a reference. To access our actual data, we'll need to dereference by # putting the array sigil (@) in front of our variable name. for my $found_carousel (@$carousels_with_bucket_forty) { print $found_carousel->name; } # We can turn it back into a scalar to find the number of matching rows. my $matching_rows = scalar @$carousels_with_bucket_forty; # Perl critic recommends putting curly braces around the reference for clarity $matching_rows = scalar @{ $carousels_with_bucket_forty }; # You can also use the arrow operator and square brackets to get data directly from the array reference. print 'The name of the first carousel is: ' . $carousels_with_bucket_forty->[0]->name; 1; ===== Evergreen Conference Sessions ===== * [[https://www.youtube.com/watch?v=fXrhpJUpFWE&ab_channel=EvergreenLibrarySystem|Making Perl Work for You in Evergreen, by Galen Charlton & Mike Rylander]] ===== Further Reading ===== * [[http://www.perlmeme.org/howtos/using_perl/dereferencing.html|Dereferencing in Perl]] from perlmeme.org