Developers

This section contains information likely to be of use to developers/programmers.

The get_property_module_data function

In this section I\'d like to talk about the get_property_module_data function.

####### Introduction

As with most things in BookyFlow, this function started out with humble beginnings, but it has evolved to play a crucial role in how BookyFlow works.

As of BookyFlow 10, it is used by many different plugins to produce output on pages. From the Extended Maps plugin, to the Property Grid plugin, to others, it\'s used extensively to display an individual property\'s details within a template.

Take a look at the fuction\'s contents on github https://github.com/WoollyinWalesIT/bookyflow/blob/master/libraries/bookyflow/functions/getproperty\ module_data.php

It\'s called thus :

When called, the function receives an array of property uids (mandatory), and optionally a path to a template file, and a template file name. If these options aren\'t used then BookyFlow will use basic_module_output.html ( for example here ) to produce the layout. It returns both the rendered template file and also the data that was used to construct that output, in an array indexed on the property uid.

####### What it looks like

{width="3.90625in" height="3.71875in"}

The default basic_module_output.html template file\'s output is relatively simplistic. This is purely for aesthetic reasons but a considerable amount of information is available in the template file, a variable dump of which you will find at the end of this section. Any of that information can be used in a template file that this function calls, so if you wanted to output the town in the template

you would just put {PROPERTY_TOWN} and voila! you have your output. (the capitalisation is important).

The Extended Maps plugin uses its own template files to render this output. The Extended Maps google maps info window doesn\'t support the use of modals.

####### Can I customise the function?

Sure!

\< BookyFlow 10.7.0

This function is kept in its own file get_property_module_data.php which in turn is included in the system by the j00001functioncall_get_property_module_data.class.php script. This means that you can copy the file to a new location (e.g. /bookyflow/remote_plugins/custom_code), copy the j00001 script to the same (or another) location and when you edit the j00001 script to point to the new function file\'s location you can then safely modify this function to suit your own needs.

>= BookyFlow 10.7.0

If you don't already have a custom functions script, first create a file called custom_functions.php in the /override_directory/custom_code directory. Next copy the code contents of /bookyflow/libraries/bookyflow/functions/get_property_module_data.php into that file.

Voila! You can now customise the function and the changes will not be overwritten when you update BookyFlow.

Data dump of values available to the called template file :

array(73) {

[\"published\"]=>

int(1)

[\"propertys_uid\"]=>

string(1) \"1\"

[\"property_name\"]=>

string(12) \"Hotel Olivia\"

[\"property_street\"]=>

string(11) \"Asheldon Rd\"

[\"property_town\"]=>

string(7) \"Torquay\"

[\"property_postcode\"]=>

string(7) \"TQ1 2QS\"

[\"property_region\"]=>

string(9) \"Andalucia\"

[\"property_region_id\"]=>

string(3) \"985\"

[\"property_country\"]=>

string(5) \"Spain\"

[\"property_country_code\"]=>

string(2) \"ES\"

[\"property_tel\"]=>

string(12) \"01000 123456\"

[\"property_fax\"]=>

string(12) \"01000 654321\"

[\"property_email\"]=>

string(13) \"test@test.com\"

[\"ptype_id\"]=>

int(1)

[\"property_type\"]=>

string(14) \"propertyrental\"

[\"property_type_title\"]=>

string(5) \"Hotel\"

[\"stars\"]=>

int(3)

[\"superior\"]=>

int(1)

[\"lat\"]=>

string(10) \"51.5006800\"

[\"long\"]=>

string(10) \"-0.1431700\"

[\"metatitle\"]=>

string(0) \"\"

[\"metadescription\"]=>

string(0) \"\"

[\"metakeywords\"]=>

string(0) \"\"

[\"property_features\"]=>

string(27) \",32,34,35,30,40,41,4,77,47,\"

[\"property_mappinglink\"]=>

string(0) \"\"

[\"real_estate_property_price\"]=>

string(1) \"0\"

[\"property_description\"]=>

string(445) \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do

eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\"

[\"property_checkin_times\"]=>

string(445) \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\"

[\"property_area_activities\"]=>

string(445) \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\"

[\"property_driving_directions\"]=>

string(445) \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\"

[\"property_airports\"]=>

string(445) \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\"

[\"property_othertransport\"]=>

string(445) \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\"

[\"property_policies_disclaimers\"]=>

string(445) \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.\"

+--------------------------------------------+-------------------------+ array(2) {
[1]=>
+============================================+=========================+ > string(1) > \"2\" +--------------------------------------------+-------------------------+ > [2]=> > \"2\" > > string(1) +--------------------------------------------+-------------------------+ > } [3]=> > \"2\" > > array(10) { > > [5]=> > > string(1) +--------------------------------------------+-------------------------+ > [6]=> > \"2\" > > string(1) +--------------------------------------------+-------------------------+ > [7]=> > \"2\" > > string(1) +--------------------------------------------+-------------------------+ > [8]=> > \"2\" > > string(1) +--------------------------------------------+-------------------------+ > [9]=> > \"2\" > > string(1) +--------------------------------------------+-------------------------+ [10]=> > \"2\"
string(1)
+--------------------------------------------+-------------------------+ [11]=> > \"2\"
string(1)
+--------------------------------------------+-------------------------+ [12]=> > \"2\"
string(1)
+--------------------------------------------+-------------------------+ [13]=> > \"2\"
string(1)
+--------------------------------------------+-------------------------+ [14]=> > \"2\"
string(1)
+--------------------------------------------+-------------------------+ > } +--------------------------------------------+-------------------------+ > } > > [\"rooms_max_adults\"]=> +--------------------------------------------+-------------------------+ > array(2) { > \"2\" > > [1]=>
array(2) {
[1]=>
> string(1)

+--------------------------------------------+-------------------------+ | > [2]=> | > \"2\" | | > | | | > string(1) | | +--------------------------------------------+-------------------------+ | > } [3]=> | > \"2\" | | > | | | > array(10) { | | | > | | | > [5]=> | | | > | | | > string(1) | | +--------------------------------------------+-------------------------+ | > [6]=> | > \"2\" | | > | | | > string(1) | | +--------------------------------------------+-------------------------+ | > [7]=> | > \"2\" | | > | | | > string(1) | | +--------------------------------------------+-------------------------+

}

}

[\"accommodation_tax_rate\"]=>

float(20)

[\"RANDOM_IDENTIFIER\"]=>

string(10) \"jlLGllrPPF\"

[\"AVERAGE_RATING\"]=>

string(3) \"8.3\"

[\"NUMBER_OF_REVIEWS\"]=>

string(1) \"3\"

[\"_BOOKYFLOW_REVIEWS\"]=>

string(7) \"Reviews\"

[\"_BOOKYFLOW_REVIEWS_AVERAGE_RATING\"]=>

string(8) \"Rating: \"

[\"_BOOKYFLOW_REVIEWS_TOTAL_VOTES\"]=>

string(12) \"Total Votes:\"

[\"COLON\"]=>

string(3) \" : \"

[\"HYPHEN\"]=>

string(3) \" - \"

[\"RATING_TEXT_COLOUR\"]=>

string(10) \"text-muted\"

[\"REVIEWS_SECTION\"]=>

string(325) \"

\<div class=\"row d - none d - md - block\">

\<div class=\"col - 5\">

\<span class=\"badge bg - success\">Fantastic\</span>

\</div>

\<div class=\"col - 7\">

\<div class=\"row\">

\<span class=\"text - success\">Rating: 8.3\</span>

\</div>

\<div class=\"row\">

\<span class=\"text - muted small\">Number of reviews 3\</span>

\</div>

\</div>

\</div>

\"

[\"REVIEWS_BUTTON\"]=>

string(187) \"

\<button class=\"btn btn - primary btn - sm\" type=\"button\"

data-bs-toggle=\"offcanvas\" data-bs-target=\"#reviewsOffCanvasjlLGllrPPF\" aria-controls=\"offcanvasReviews\">

Show reviews

\</button >

\"

[\"RIBBON\"]=>

string(106) \" \< div class=\'ribbon 000000\' >\<span class=\'\' style = \'background:#90EC33;color:#000000;\' > Fantastic\</span >\</div > \"

[\"UID\"]=>

int(1)

[\"THUMBNAIL\"]=>

string(67) \" / Joomla_4 / bookyflow / uploadedimages / 1 / property / 0 / thumbnail / ihallway . jpg\"

[\"IMAGELARGE\"]=>

string(57) \" / Joomla_4 / bookyflow / uploadedimages / 1 / property / 0 / ihallway . jpg\"

[\"IMAGEMEDIUM\"]=>

string(64) \" / Joomla_4 / bookyflow / uploadedimages / 1 / property / 0 / medium / ihallway . jpg\"

[\"IMAGETHUMB\"]=>

string(67) \" / Joomla_4 / bookyflow / uploadedimages / 1 / property / 0 / thumbnail / ihallway . jpg\"

[\"PROPERTY_DESCRIPTION\"]=>

string(445) \"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua . Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat . Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur . Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum . \"

[\"PRICE_PRE_TEXT\"]=>

string(12) \"Prices from \"

[\"PRICE_PRICE\"]=>

string(9) \"110.00€\"

[\"PRICE_POST_TEXT\"]=>

string(15) \" & nbsp;Per night\"

[\"PROPERTY_UID\"]=>

int(1)

[\"LIVE_SITE\"]=>

string(25) \"http://localhost/Joomla_4\"

[\"MOREINFORMATION\"]=>

string(9) \"Read more\"

[\"QUICKINFORMATION\"]=>

string(10) \"Quick Info\"

[\"MOREINFORMATIONLINK\"]=>

string(32) \"/Joomla_4/en/hotel-olivia-1/view\"

[\"STARSIMAGES\"]=>

string(225) \"\<img src=\"/manual/ Joomla_4/bookyflow / assets / images / star . png\" alt=\"star\" border=\"0\" />\<img src=\"/manual/ / Joomla_4 / bookyflow / assets / images / star . png\" alt=\"star\" border=\"0\" />\<img src=\"/manual/ / Joomla_4 / bookyflow / assets

/ images / star . png\" alt=\"star\" border=\"0\" />\"

[\"SUPERIOR\"]=>

string(83) \"\<img src=\"/manual/Joomla_4/bookyflow/assets/images/superior . png\" alt=\"superior\" border=\"0\" />\"

}

Minicomponents

Minicomponents are scripts in BookyFlow which are designed to be discovered and used by BookyFlow to add, provide, or override functionality in the system. In simpler terms, they\'re discrete sections of software that perform a certain function. They are similar to hooks in Wordpress and Events in Joomla such as onContentPrepare. I originally came up with the idea of using trigger numbers back in the summer of 2005. Since then several times I have considered replacing the numbers with more descriptive event names but the number system is well understood and well documented so it\'s not really necessary to refactor them.

The most complete, up-to-date list of these trigger numbers and what they do can be found in the /core-minicomponents directory on Github. Scroll to the bottom of that page.

BookyFlow comes with a core set of minicomponents, which are installed in the

/bookyflow/core-minicomponents/ directory. If you are looking to modify any core minicomponent, I would discourage you from editing them in-situ. Instead, you should copy any file you want to edit to the /override_directory/ directory, and then a sub-directory called /custom_code/ and make changes to the file there.

The term Minicomponents is derived from BookyFlow\' history. In the past, when I devised how to add functionality on the fly users would install this additional functionality via the Joomla component installer, hence the term minicomponents.

Nowadays a minicomponent is a file whose naming convention follows the style jNNNNNXXXXX.class.php (for example j00006sanity_checks.class.php), and is usually installed via the BookyFlow Plugin Manager, but it\'s also possible for you to create the file in the directory and use the Rebuild Registry feature to tell BookyFlow that it exists.

Minicomponent Registry

The registry in BookyFlow (stored in /bookyflow/temp/registry.php) is a record of all files that BookyFlow can run as discrete scripts.

Originally (in V2 of BookyFlow) these files would be automatically discovered by BookyFlow each time it ran, however as time went by we realised that as a system\'s library of minicomponents grew, this discovery process could potentially slow a system down so I broke the minicomponent\'s handling down further to the minicomponent registry, and the mcHandler class.

The registry is basically the record of where all the runnable files exist, whilst the mcHandler actually calls these scripts to be run. As a developer you should never need to manually edit this file. If you want a new minicomponent to be recognised and used by the system you should use the Rebuild Registry button in the administrator area of BookyFlow. In effect, all this button does is deletes the registry.php and registry_classes.php files from the /bookyflow/temp/ directory and forces BookyFlow to rediscover all runnable minicomponents. You only need to use this button once each time you copy a core minicomponent to a subdirectory in the /override_directory folder, or add a new one. You don\'t need to run it each time you edit these files. The registry is simply a record of these file\'s locations, not their contents.

The registry is rebuilt occasionally.

  • If BookyFlow sees that the registry file is about 24 hours old, it'll rebuild the registry.

  • If a plugin is installed/uninstalled then it'll rebuild the registry.

  • Developers can force the registry to be rebuilt manually through the admin area > tools > rebuild registry feature.

  • If the registry.php file does not exist in /bookyflow/temp then the registry will be automatically created.

When the registry is rebuilt, BookyFlow scans certain directories in a specific order

  1. First it scans the /bookyflow/core-minicomponents/ directory

  2. Next it scans /bookyflow/core-plugins/ directory. If it finds any sub-directories it checks each one of those for scripts with the jnnnnnxxxxx.class.php or xxxxx.class.php naming pattern.

  3. Next it scans /bookyflow/remote_plugins/ for any subdirectories.

  4. Finally it finds the current CMS's theme or template and searches for a directory called

theme_name/html/com_bookyflow/

As it scans each directory for the requested file name pattern, each found file is added to the registry. If a filename is found that's the same as one found before, the new file replaces the original. So, for example if it finds a file called j01060slideshow.class.php in the

/html/com_bookyflow/ directory then that will be used instead of the file j01060slideshow.class.php in the /bookyflow/core-minicomponents/ directory.

As a result, it's possible to have several scripts with the same name (e.g. j01060slideshow.class.php) in different places in the directory structure. If you're customising scripts then, because you now know that the inclusion order is core-minicomponents ->

core-plugins -> remote_plugins -> the theme/template's /html/com_bookyflow directory you know

which script is likely being used. If, for example, a script exists in both core-minicomponents and the /override_directory/custom_code directory, then the one in custom_code will be used.

Developing Tips and Tricks

Here we\'ll discuss some techniques we use when developing plugins for BookyFlow.

Different minicomponents are called at different times, depending on their trigger number. We\'ll refer to these types of scripts by their trigger number, and occasionally offer examples where you can see them in use.

####### Useful variables & functions

get_showtime(\'ePointFilepath\')

Calling this function will give you the absolute path to whichever script is being run. If you\'re using template files to generate layout (and you should be), however you\'ll need to do something like

to tell the \$tmpl object where your custom template file is located. As a plugin developer you should be distributing plugins that are compatible with BookyFlow\' own templates (Bootstrap 2 and Bootstrap 3 & Bootstrap 5) in respective directories templatepath/bootstrap and templatepath/bootstrap3 templatepath/bootstrap5.

Hint : If you intend to call other minicomponents from this minicomponent, call get_showtime(\'ePointFilepath\') and put the results in a variable before calling another minicomponent. The instant the next minicomponent is called, get_showtime(\'ePointFilepath\') is reset to the next minicomponent\'s absolute path.

get_showtime(\'eLiveSite\')

This is a little similar to ePointFilepath, in that it points to the directory this script\'s running in, relatively from the base of your website. Let\'s say that your website\'s at http://www.domain.com, then eLiveSite will point to the url http://www.domain.com/bookyflow/remote_plugins/xxxxxx/

In the flipwall plugin you\'ll see that we use this variable to include the flipwall\'s jquery.flip.js file in the host CMS\'s header, like so :

BookyFlow_get_relative_path_to_file

> BookyFlow 10.7

In 10.7 there's a new function called bookyflow_get_relative_path_to_file()

This was written to allow simple overriding of Core css and javascript files. Sometimes you know the absolute location of a file, but not its relative path. This function will return the relative path to a known file, typically so that you can add it to the document's head, e.g. by using the bookyflow_cmsspecific_addheaddata function.

j00005 scripts

These are generally your setup scripts, where you include functions files, import classes and include language files.

Here we\'re looking to find the current language\'s language file for this plugin. If it doesn\'t exist, we\'ll fall back to the english language file for this plugin (if it exists).

Switching stuff off

Ok, that\'s mundane enough, let\'s try something a little bit more fun.

Let\'s say that our plugin introduces functionality so unique that we want to disable certain things inBookyFlow, based on certain conditions. Let\'s see how Jintour\'s j00005get_jintour_property_data.class.php file does things.

In a Jintour based property, we can\'t show the normal dashboard, because Jintour bookings aren\'t the same as normal bookings, so to switch off the standard dashboard script, we do the following :

How cool is that? Just like that, for Jintour based properties, with one line we\'ve switched off (among other things) the dashboard calendar.

Redirecting template calls

Something else we can do, and we typically do this in j00005 scripts, is redirect calls from one of the core template files, to another template file. Again, Jintour\'s j00005 script gives us an example of how this is done :

Jintour based properties have less information to show in the property details, so in the event that the currently viewed property is a jintour property (see that script to see how we determine that) we tell BookyFlow to use the edit_property.html file in our /templates directory, not the one in

/bookyflow/templates/bookyflow/backend. Singletons

BookyFlow makes use of Singletons for a variety of reasons. The main one being that we can ensure that data is called just once and it is retained throughout a run. BookyFlow can be triggered in a number of ways, e.g. through the component itself, or via modules and plugins (mambots) consecutively. This would mean some database intensive queries could be called several times, so we sidestep this by using singletons to retain the information called and then reuse it later.

There\'s a special singleton in BookyFlow called \"Showtime\" ( named after my favourite server on Novalogic\'s Delta Force 2, yes I know I\'m a geek ) which can be used to store data throughout a run. Let\'s say you\'ve generated some data in a 00005 script that you know you\'ll use later in another script. You can use the Showtime variables to retain the information temporarily, like so

:

and then use it later by calling

Just remember that the data isn\'t persistent. Once the run completes the data is lost, so if you want to maintain that information you\'ll need to store it somewhere more permanent.