Formulize is a complex piece of software, that has grown organically over many years. The basic idea is that the user (a webmaster of some kind) has defined a form, and the rules for who can interact with the form, and how they can interact with the form. Formulize reads all that configuration data, and dynamically generates a user interface based on the configuration.
Formulize is a web-based software written in PHP. It resides on a web server, and communicates with a client (web browser) through the http protocol. The server responds with a normal stream of HTML and CSS and Javascript code, and the web browser does the rest.
Formulize is 20 years old. What started out as a simple form generator, is now a full database application creation environment. The flow of execution throgh the code has got more complex and nuanced. This page tries to explain how it works.
Formulize began as a module in the XOOPS cms. XOOPS was forked several times and fizzled out as Drupal and then WordPress gained popularity. One prominent fork was ImpressCMS, and that is the version that the standalone version of Formulize is based on. Architecturally, the Formulize code is still a module inside the XOOPS/ImpressCMS system, and the lowest level operations, session management, database i/o, basic page rendering, etc, are all handled by the underlying cms.
Here is a partial listing of the files and folders in Formulize, and what they do. These are the main ones that are key to making the website operate. There are a lot of other files and folders besides these!
index.php
This is the file that starts every Formulize page load. A typical URL in Formulize would be: https://mysite.com/modules/formulize/index.php?fid=6
When such a URL is requested, this file includes the core mainfile.php, which sets up the user’s session and various other “housekeeping.” Then it includes header.php which starts up the theme and template systems. The index.php file includes Formulize’s own initialize.php file, which leads to the main execution of Formulize. Lastly, this file includes footer.php which renders the page contents using the theme and template system that started up inside header.php.
However, if a $formulize_screen_id is set, then this file will not call mainfile.php, or header.php, or _footer.php. Instead processing will proceed directly to initialize.php. This is because we assume that if $formulize_screen_id is already set, then someone is working with Formulize in PHP code, rather than making a request via the URL. We assume they know what they’re doing and will have included the necessary core files themselves.
If you want to follow the full XOOPS/ImpressCMS bootstrap flow, mainfile.php includes include/common.php, which then ultimately invokes a series of classes in the libraries/icms/ folder, and elsewhere, including handling the session, establishing the database connection, etc.
initialize.php
This file does a lot of basic checks and gathering of information, including a basic security check to see if the user has permission to view the requested form. The requested form is determined based on the URL parameters fid or sid. They stand for form id and screen id. Alternatively, if $formulize_screen_id was already set, then that will be used to determine which screen to display.
Prior to rendering the list of entries or the form, this file calls include/readelements.php which is the single file that handles all the reading of data submitted from a form. If the user submitted data from the prior pageload, the readelements.php is how that data gets written to the database.
Once readelements.php is finished, then execution hands off to the relevant classes for rendering the screen. If a form was requested rather than a specific screen, the default list screen for that form will be displayed (unless the user only has permission for a single entry in the form, in which case the default form screen will be displayed instead).
If a form was requested, but it has no default screen declared, then the displayEntries or displayForm functions are called, depending on the user permissions and form settings. This low level rendering, bypassing screens, is also used when master.php is requested (instead of index.php).
class/listOfEntriesScreen.php or class/multiPageScreen.php (or other screen classes)
If a screen is being rendered, execution will flow to the appropriate class file. These files contains the classes for list of entries screen objects, form screen objects, etc, which contain all the configuration settings for those types of entities in Formulize. These files also have handler classes that have a render method to display a screen based on a given object of that type.
When the render method of the handler is called, it in turn calls the displayEntries function in the include/entriesdisplay.php file for lists of entries. Or the displayFormPages function in the include/formdisplaypages.php file for forms. The screen object is passed to those functions, so the screen settings can be taken into account as the rendering happens.
include/entriesdisplay.php
This file contains the function displayEntries which reads the status of things based on the URL, the logged in user, and the data submitted from the prior page load. Based on that, and the screen settings, it then draws the list of entries, or if the user has drilled down into an entry, it hands off execution to a form screen (or the displayForm function directly if no screen is specified).
When displaying a list of entries, execution is passed to various other functions in the file, and other files. Here are the major operations it performs:
First, the saving and loading of Saved Views is performed. Saved Views are collections of settings used to define what columns and searches, etc, are in effect. Saved Views can be used to control the starting configuration of a screen. End users might also save views, so they can quickly return to a set of options that is useful to them. On any given page load we could be saving a new view, or loading up a previously saved view.
Any Custom Buttons that were clicked on the prior page are processed. This is so they have a chance to affect data prior to the data being gathered.
A determination is made of whether the user has requested a specific entry, and if so what screen do we hand off execution to so that the entry can be displayed. This happens if the user has clicked the icons for editing/viewing a specific entry. If execution hands off to another screen, then no further execution occurs in entriesdisplay.php.
We call getData in the include/extract.php file, which retrieves the data to display in the screen. The getData function retrieves all data for any dataset, regardless of the number of forms or the way they are joined.
We call drawInterface (in this same file) which determines what UI elements are available for above the screen, and then renders the toptemplate.html for the screen.
We call drawEntries (in this same file) which determines what UI elements are available in the list of the screen, and then renders the openlisttemplate.html, then loops through all the records in the dataset and displays each one using the listtemplate.html, and then renders the closelisttemplate.html
Back within the displayEntries function, it renders the bottomtemplate.html for the parts of the page below the list of entries.
include/formdisplaypages.php
This file contains the function displayFormPages which reads the status of things based on the URL, the logged in user, and the data submitted from the prior page load. Based on that, and the screen settings, it figures out which page to display and then hands off rendering of the actual HTML form to the displayForm function in the include/formdisplay.php file.
include/formdisplay.php
This file contains the function displayForm function which reads the status of things based on the URL, the logged in user, and the data submitted from the prior page load. Based on that, and the screen settings, it gathers the necessary elements to display, figures out which page to display and does the rendering of the actual HTML form.
This file contains several other important functions and classes, which are called at various times in the process of displaying the form. Here are the major ones:
The formulize_themeForm class, which extends the underlying XOOPS theme form class, but includes many customizations for displaying Formulize forms, including handling the rendering of all the templates for the form screen.
getEntryValues which gathers the current values from the database for a given entry so they can be displayed in the form when editing an entry
drawSubLinks which has extensive code related to the rendering of subform elements, which are elements that contain entire entries from another form
compileElements which loops through the elements that are part of the page, and converts the Formulize configuration settings for each one into a XOOPS form element object, which can be rendered in the formulize_themeForm class (this conversion happens in the include/entriesdisplay.php file, and the class/elementrenderer.php file)
loadValue which takes the values from the database for a given entry, and injects them into the Formulize configuration settings for a given element, so that when the element is rendered, it shows the saved value instead of its default value
writeHiddenSettings which creates hidden elements to include in the form that will pass back various indicators of what has happened on this page load, so the next page load has the right cues to start where this one left off
drawJavascript which contains all the Javascript code that makes the interactive elements of the form work
include/elementdisplay.php
This file primarily contains the displayElement function, which figures out if the user has permission to see a given form element, within a given entry, and if so, it converts the Formulize configuration settings to a XOOPS form element object. This conversion happens by calling the elementrenderer class in class/elementrenderer.php.
The XOOPS form element objects are rendered later in the formulize_themeForm class (found in include/formdisplay.php).