As a developer working on your clients sites it\'s quite possible that you will want to use some of the functionality in BookyFlow, but in your own scripts.
The best way to do that is by using the \"Alt Init\" plugin.
Once you have done that you can then use BookyFlow framework code snippets in your own scripts. Naturally you will probably need to change the paths from what's shown in this example to something that suits your environment.
####### Introduction
In this article I will show you how to create a simple BookyFlow plugin called Hello World.
It assumes that you\'re already familiar with working with PHP scripts, the purpose here is to demonstrate how you can create a simple plugin with code that can be used on both Joomla
and Wordpress installations of BookyFlow. It also assumes that you have a working installation of BookyFlow up and running.
Once it has been created you will be able to enter the \"hello_world_simple\" task in the address bar of your browser, like this :
{width="4.927083333333333in"
height="0.3541666666666667in"}
And you will see simple output like this in the page
{width="6.448332239720035in"
height="1.2090616797900262in"}
There are other ways to display the output, but in this example we\'ll stick with this simple example.
####### The Code
Ok, let\'s get started. First you need to navigate to your /bookyflow/remote_plugins directory and create a new directory called hello_world_simple
{width="4.65625in" height="1.3020833333333333in"}
Once that has been done, you need to create your plugin information file. The file should be called plugin_info.php and it\'ll contain the following data :
As you can see the class name and the name in the \$this->data array \"name\" index must match the plugin name and the parent directory.
Save that file. Next you need to create a new file called j06000hello_world_simple.class.php in the same directory.
{width="5.46875in" height="1.2708333333333333in"}
The basic structure of a plugin file is that it starts with JNNNNNXXXXX.class.php
For a complete breakdown of BookyFlow trigger numbers, see the README.md on Github (you\'ll need to scroll to the bottom),
In this file you will need to enter the following lines
This is a very simplistic example of a plugin. If you were to copy it you would only need to change the name of the class (this is what defines the name of the \"task\" that you will call) and the actual code performing the work, in this case just
Now, before BookyFlow can use this script it needs to be added to the internal BookyFlow registry. Once you have saved the file you need to rebuild the registry, this will tell BookyFlow that the script files exist.
{width="6.448748906386702in" height="2.59875in"}
You only need to rebuild the registry once, when you create the file ( including after copying a core file to a directory in /remote_plugins/xxxxx this tells BookyFlow to use this one instead of the original.)
Ok, that\'s it, all done! You can now call the task directly through the browser\'s address bar, as shown at the top of this page, by entering something like http://localhost/test/index.php?option=com_bookyflow&task=hello_world_simple in the browser.
There are other ways it can be called too, for example through shortcodes, or BookyFlow ASAModule.
####### Introduction
BookyFlow, as a plugin for both Joomla and Wordpress, does not stand in isolation. Instead it is part of a larger set of moving parts that make up your Content Management System.
It\'s not possible (for me) to lock down an installation of BookyFlow so that malicious or faulty code in other plugins cannot access the data in BookyFlow tables. I can secure the system as much as possible, however vulnerabilities in other areas of the CMS or its plugins are outside of my control and there\'s always a risk that guest or manager data might be exposed to unauthorised users.
Article 33 of the GDPR outlines personal data breach reporting requirements, specifically addressing when organisations must report breaches and within what timescales. Failure to report breaches, and address those breaches after the fact, can result in heavy fines. As the developer of GPL software that offers absolutely no warranties whatsoever I would not be affected, however my clients would be and I consider it both a professional and moral duty to ensure that the risks to them are minimised as much as possible.
While planning how BookyFlow would be compliant with the GDPR I realised that this was the right time to introduce the user encryption that I had wanted for a long time to implement. The goal was that, even if guest and manager PII (personally identifiable information) should somehow be exposed, this exposure should do no harm because this information would be encrypted and of no use to attackers.
As a result, in the spring of 2018 BookyFlow was modified so that all existing guest data was encrypted in new installations and any sites that were updated with the newest version. This
brings its own set of problems in that coders find it more difficult to access guest data when generating their own reporting tools. In this section I\'ll describe how those coders should use the BookyFlow framework to extract the information that they want.
encryption_key.class.php
This particular file deserves special mention, because without it you will find it impossible to decrypt guest and manager data.
The file encryption_key.class.php was introduced in the middle of 2018.
Its purpose is to allow the system to encrypt and decrypt Personally Identifiable Information (PII), I.E. guest and property manager\'s sensitive information.
If the file does not exist, on installation it is immediately created and put into the BookyFlow root directory, e.g. public_html/bookyflow. You can move this file, indeed it is recommended that you move it outside of the web server\'s root altogether and modify /bookyflow/configuration.php and set the \$jrConfig[\'secret_key_location\'] value to the absolute path of its location.
Because this file is vital to decrypting your guest and manager data, you must not modify it and
you must keep it safe at all times. Without it it\'s not possible to decrypt said data.
####### An example module
To decrypt PII for your own use, you cannot simply access the BookyFlow tables that contain this data. Instead you need to include the BookyFlow framework and use its built-in functionality to decode an individual\'s data.
Given that the majority of BookyFlow users are hosted on Joomla, this example will refer to a \"module\", however Wordpress developers will be able to use similar concepts when building widgets or other applications for Wordpress. If you want to see one such example, open up the \"BookyFlow Search\" widget included in the BookyFlow Wordpress Quickstarts. The principles are largely the same.
Including the framework is simple enough, however I\'ll break down the steps, for clarity. I will assume that you already have sufficient coding skills to build a basic module or application for Joomla or Wordpress.
If not already defined, we will define _BOOKYFLOW_INITCHECK otherwise BookyFlow scripts will not run.
Next we will check for the existence of a definition called BOOKYFLOW_ROOT_DIRECTORY. Before getting permission to be listed on the Wordpress plugin directory it was their insistence that whilst BookyFlow might be able to run from its own unique path, that path must be changeable by the site administrator. Although I thought it was an unnecessary complication, those were the rules and I have to abide by them.
Finally, we will include a BookyFlow plugin called alt_init.php. This plugin is able to include the entire BookyFlow framework without you needing to do any more work.
Decrypting guest data
Before we start, you will find that there are two guest tables : xxx_bookyflow_guests and xxx_bookyflow_guest_profile. Why, you ask?
The reason is primarily historic. BookyFlow was first conceived in 2005, and since then millions of lines of code have been added and removed from it. The bookyflow_guests table was the first one added, and the guest_profile table was added some years later as a way for guests to change their own data and have that change trickle down to hotels that they had previously booked at. At the same time, I didn\'t want changes made by one hotel to be reflected back to the guest profile table and thence to other hotels, perhaps the hotel has rather unprofessionally left some comments that should stay with just that hotel?
If you want to access guest data, if the user you are accessing is a registered user in the system, you can query them by their cms id and look for their details in the guest profile table. See Method 2.
If the guest might not be a registered user you must first know the id of the property that they are a guest of, and of course their id. Once known you can use the jrportal_guests class to pull their data out. This class will handle the decryption for you.
Method 1
Method 2
In the next scenario, the user is a registered user, perhaps they\'re logged in and you want to pull their information for display into a module or widget.
In this module, we will assume that you already know the guest\'s cms id. If you don\'t, you can get it by doing
in Joomla, or
in Wordpress.
We will include the encryption class from BookyFlow, and create a new instance.
Now we are ready to pull the data from the guest profile table.
This pulls the encrypted data from the database. Next we need to decrypt it.
You now have the guest\'s first name as stored in the database for use in your own code.
Encrypting guest data
Now that you know how to decrypt guest data, encryption you will see is the opposite. To save a guest as a guest of a given property :
jr_import( \'jrportal_guests\' );
\$jrportal_guests = new jrportal_guests();
\$jrportal_guests->id = \$id;
\$jrportal_guests->property_uid = \$property_uid;
if (\$id > 0 ) {
\$jrportal_guests->get_guest(); // if we don\'t get_guest then the mos_id ( cms_id) will get reset when the guest is saved
}
\'\');
\'\');
\$jrportal_guests->firstname = bookyflowGetParam(\$_REQUEST, \'firstname\',
\$jrportal_guests->surname = bookyflowGetParam(\$_REQUEST, \'surname\',
\$jrportal_guests->house = bookyflowGetParam(\$_REQUEST, \'house\', \'\');
\$jrportal_guests->street = bookyflowGetParam(\$_REQUEST, \'street\', \'\');
\$jrportal_guests->town = bookyflowGetParam(\$_REQUEST, \'town\', \'\');
\$jrportal_guests->region = bookyflowGetParam(\$_REQUEST, \'region\', \'\');
\$jrportal_guests->country = bookyflowGetParam(\$_REQUEST,
\'guest_country\', \'\');
\$jrportal_guests->postcode = bookyflowGetParam(\$_REQUEST, \'postcode\',
\'\');
\$jrportal_guests->tel_landline = bookyflowGetParam(\$_REQUEST,
\'landline\', \'\');
\$jrportal_guests->tel_mobile = bookyflowGetParam(\$_REQUEST, \'mobile\',
\'\');
\$jrportal_guests->email = bookyflowGetParam(\$_REQUEST, \'email\', \'\');
\$jrportal_guests->vat_number = bookyflowGetParam(\$_REQUEST,
Guest profiles table
Unfortunately I don\'t yet have a class for guest profiles, so have a look in j06005save_my_account.class.php to see how guest profile records are saved.
In this section I am going to discuss how you as a developer can use the code in minicomponents to help you to call discreet BookyFlow scripts.
This information is helpful to you if you want to include code from BookyFlow into other scripts, or just if you\'re building your own minicomponent.
The section actually addresses two distinct scenarios, the first is how to access a minicomponent you\'ve written yourself, and the second is how to include rendered snippets from a minicomponent into your own code. As a developer you are probably more interested in the second part, but I recommend you read the first part so that you can understand how things are interconnected.
####### Getting started with the code
Let\'s dive right in.
These examples are taken from the Show Property Reviews script on Github
https://github.com/WoollyinWalesIT/bookyflow/blob/master/core-minicomponents/j06000show_prop erty_reviews.class.php
This is what you will see at the top of the script.
Before I continue, I should point out that one argument that\'s always missing from this list of options is \"output_now\". Most minicomponents that output stuff to the page have it, so in general you can assume that it\'s available but if not you should check out the minicomponent script itself to be sure. Note, this is only relevant if you are calling one script from another. If you are calling the script via the url (more on that in a moment) you can assume that the output will be immediate.
I should also point out that the shortcode_data at the top of the scripts isn\'t used by the script itself in any way. It\'s there solely to allow the Admin > BookyFlow > Tools > Shortcodes page to generate its output. It is, however, useful to you as a developer. You don\'t need to refer to each script to see this information.
The Shortcodes page in the administrator area will use this information to build a shortcode suggestion like this : [bookyflow task=\"show_property_reviews\" params=\"&property_uid=1&reviews_limit=3\"]
####### Calling via the url
If you are developing your own minicomponent and you want to test it to see how it looks, you could go through the process of adding scripts to menus, but often that\'s not needed.
Fortunately, you don\'t need to do that.
You can call 06XXXX minicomponents directly from the url.
Firstly, please remember that if you\'ve built a new script that looks something like j06000xxxxx.class.php (or 06100/06200/06500) then don\'t forget to rebuild the registry once you have created it. That tells BookyFlow that the script exists. Once you\'ve done that you can do the next step.
Let\'s assume that the site I\'m working on generates urls that look like http://localhost/Joomla_4/index.php?option=com_bookyflow&view=default&Itemid=103 or http://localhost/wordpress-5.9.3/index.php/bookings/?option=com_bookyflow& (Joomla and Wordpress respectively) when I\'m on a BookyFlow page. I\'ll refer to these urls as {URL} from now on.
If I want to call the Show Property Reviews page directly from the address bar of the browser, I can by putting together the information from the shortcode to create a url that looks like
{URL}&task=show_property_reviews&property_uid=1&reviews_limit=3
If I put that into the address bar of the browser, then the property reviews page will show.
You might be thinking \"So what? I can get that from the page itself.\" and you\'d be right. What I\'m doing here is demonstrating to you how to use information in ways that might not be immediately obvious to you.
####### Pulling rendered snippets in your own code
Moving on, let\'s assume that you are a developer who wants to include BookyFlow output in his or her own page.This saves you bucketloads of time because you don\'t want to reinvent the wheel. I\'ve already done that for you, all you need to do is work your own magic.
So, instead of telling you to dig into the code of such a large system as BookyFlow to see how to do it, I\'ll use the shortcode as a shortcut to help you out.
Remember, the shortcode for property reviews looks like this : [bookyflow task=\"show_property_reviews\" params=\"&property_uid=1&reviews_limit=3\"]
Now, as the developer you will first need to pull in the BookyFlow framework so that you can use what\'s on offer. That is described in the Using the BookyFlow Framework section. Once you have access to the BookyFlow framework you can then call a script like this :
Notice how the argument output_now is set to false? This tells the script to return the rendered template instead of showing it.
Now that you have this wonderful nugget of information, you have learned that you can do the same with other shortcodes.
####### Extrapolation
Take a look at the Property features shortcode
[bookyflow task=\"show_property_features\" params=\"&property_uid=1\"]
To include that code in your own script you would do this :
Another example :
[bookyflow task=\"show_property_slideshow\" params=\"&property_uid=1\"]
####### Conclusion
So, here I have shown you ways that you can use the BookyFlow framework in ways that you may not have been previously aware of. Hope it helps.
Here I will give you a brief overview of how to install and create pseudocron jobs for BookyFlow.
####### In brief
BookyFlow supports a pseudo cron system, IE a system that works a bit like timed jobs in linux (cron). Cron jobs are called on a timed basis depending on how the cron job was installed (this cannot be changed at a later time, except by manually editing a table).
As a plugin developer, you will want to tell BookyFlow that there are scripts you want to call on a timed basis. You do this in the plugin_install.php of your plugin. An example can be seen on the Creating plugins page.
This functionality \"registers\" the cron job with the pseudocron functionality, and the intervals are as follows.
\"M\": // Every minute
\"QH\": // Every quarter hour \"H\": // Every hour
\"D\": // Every day \"W\": // Every week The cron job file itself
A cron job file is just like any other 06000 task, ie it can be called by anybody, assuming that the menu linking to BookyFlow allows unregistered users to view it.
####### Conclusion
That\'s it. It\'s very simple. Create a 06000 task that \"does stuff\", then use \'\'addJob\'\' in \'\'plugin_install.php\'\' to tell BookyFlow to call it from time to time.
BookyFlow supports having template overrides in templates/themes, however sometimes you need to take things further.
The majority of our users are developers who are setting up sites for their clients. For them, the standard template override feature is sufficient, they make the changes the client requests then move on.
Some of our users, however, are long-time BookyFlow users (thank you!) and for these users, if they update a template like Leohtian, their existing overrides can be overwritten when the template is updated. This is where Template Override Packages (TOP) come in.
These are also useful if you want to distribute a BookyFlow template set, but not a WordPress theme/Joomla template. A BookyFlow template package should work in both WordPress and Joomla without any changes.
What\'s in a TOP plugin?
A typical TOP plugin will have a plugin_info.php file, a minicomponent with the trigger number 00001 and a number of template files.
Let\'s take a look at the Template Package Booking Form Layouts plugin together, this will help you to understand.
{width="6.448116797900262in"
height="1.1484372265966754in"}
This plugin info file has a class called plugin_info_template_package_booking_form_layouts, and if you open it you will see some basic plugin information. If you intend to create your own template packs, then you will need a plugin_info.php file. You must ensure that the name of the class is changed to reflect your own template pack\'s name.
The \$this->data name array key should also reflect the name of the pack in the same way that the class does. Aside from those two fields, if you do not intend to distribute this plugin then you don\'t really need to do much with the rest of the data in the plugin_info.php file.
The next file in our example plugin is called j00001template_package_booking_form_layouts.class.php
The 00001 number ensures that this script is triggered as soon as BookyFlow starts. The important lines in this file are :
Let\'s break down what it does.
This line sets the plugin\'s name. It can be anything you want but it needs to be valid PHP as it is used as the template package array index, so something like \"my_first_template_pack\" would work fine, however \"my first template pack\" would not.
The absolute path relative to the server\'s root, of the location of this script.
This is then changed to determine the path to these template files, relative to BookyFlow\' root. If you are making your own package then it\'s safe to just copy these two lines.
\"showtime\" in BookyFlow is a singleton object that is used to make information available to various scripts on BookyFlow. Here we are pulling the variable \"template_packages\" from the showtime object. If it\'s not yet set then we will set it to be an empty array. Again, you can just copy this into your own 00001 script.
In the example plugin there are actually three templates that are overridden, but I will only show the main override here.
Here\'s where we define the template we intend to override, in this case dobooking.html which is the template file that is used by hotels/B&Bs etc. We give this a title and a description. As of
9.9.3 the description and any screenshot aren\'t yet used, this is functionality we will provide later if the feature proves popular.
Finally we save this new information to the showtime object. Once installed this information is then available to the Template Override Packages page.
A real world example
Documenting a feature is all very well, but practical examples where you can see a use for a feature will help even more, so let\'s have a look at a common requirement.
NB: This particular tutorial was written for the Leohtian template. That template is no longer being used; however the basic functionality is still valid.
Many users have different requirements for what is displayed on a BookyFlow page. I have long taken the view that it\'s easier for me to collate as much information as is relative to a template, and add it. That way, it\'s easier for users to remove the information they don\'t want, instead of having to ask me how to add more.
For example, we will show you the Random Accommodation plugin which you often see on the front page of BookyFlow Leohtian sites
{width="4.0625in"
height="3.5208333333333335in"}On hover you can see a Read More button.
Clicking on that opens up a modal like this
{width="6.395833333333333in"
height="2.213292869641295in"}
Let\'s say, for example, that we don\'t want to show the address details in this template. We could modify this file, but if the Leohtian template is updated any changes we make to this file will be lost, therefore we are going to make a TOP plugin. This plugin can then be zipped up and uploaded to multiple BookyFlow sites, or even sold on to other BookyFlow users if you think they\'ll like the pack.
First we will make a new directory in the remote plugins, like this :
{width="6.395833333333333in"
height="1.1471555118110237in"}
Inside that directory I will create a new plugin_info.php file, and in that I will put this :
Next I will create a 00001 script which tells BookyFlow that files are available. I\'ll call it j00001my_first_template_package.class.php and it will contain :
Once I have created that file, I will need to rebuild the registry to make sure that BookyFlow includes this script every time it runs.
Now I can copy property_header.html from the \templates\jr_leotian\html\com_bookyflow directory into this one. When I\'ve chosen this template in the Template Override Manager then this version of that file will be used instead of the one in \templates\jr_leotian\html\com_bookyflow.
When that\'s done I can customise this file as much as I want to remove the address details, this file will not be overwritten when Leohtian is updated.
Distribution
If I want to re-use this package on other installations, all I need to do is zip up the contents of the directory.
{width="6.356754155730534in"
height="0.9011231408573929in"}
With these files in a zip file, you can use the BookyFlow Plugin Manager Third Party Plugins page to upload these changes to other sites.
Updates
In the plugin info file you should also add some information if you plan to distribute the plugin.
These two lines will tell BookyFlow where it can get updated version information about the plugin, and offers a link to a url where the update can be downloaded from. This could be a direct link, or to a shop page.
Your template versions file should be a json file : my_first_template_package.json which contains the following information.