The flow through the code
Introduction
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.
Code organization
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!
- Root Folder of Website
- mainfile.php « bootstraps the entire system, included at the top of every page generation process
- header.php « starts up the theming and template engine (which is Smarty)
- footer.php « renders the page contents using Smarty
- libraries
- icms « the core files that drive all basic operations, the db connection, the user session, page rendering, etc
- modules
- formulize « where the magic happens
- index.php « handles all formulize page requests, hands off to initialize.php
- master.php « alternate starting point for Formulize requests, that ignores screens and renders the most basic version of the list/form, which is useful for seeing all entries in a form, regardless of any screen settings that might hide certain things
- initialize.php « primary routing controller, figures out what functions/classes/methods to call to render the page
- admin « all the logic for generating backend admin pages and saving configuration data
- blocks
- mymenu.php « the logic for generating the elements in the sidebar menu
- class
- data.php « the data handler class
- elementrenderer.php « where the Formulize config data is turned into a renderable XOOPS form element object
- elements.php « the base class for all form elements
- checkboxElement.php « any file ending in ‘Element.php’ is a class file for a specific element type
- screen.php « the base class for Formulize screens
- formScreen.php « handles legacy Form screens, hands off rendering to include/formdisplay.php
- multiPageScreen.php « handles Form screens, hands off rendering to include/formdisplaypages.php
- listOfEntriesScreen.php « handles list-of-entries screens, hands off rendering to include/entriesdisplay.php
- templateScreen.php « handles template screens
- calendarScreen.php « handles calendar screens, hands off rendering to include/calendardisplay.php
- frameworks.php « the form relationship class
- include
- formdisplay.php « handles rendering of forms, includes an extension of the XOOPS form class to render elements
- formdisplaypages.php « handles rendering of the multipage structure of form screens, hands off to formdisplay.php
- elementdisplay.php « makes renderable XOOPS form element objects, hands off to class/elementrenderer.php
- entriesdisplay.php « handles rendering of data into interactive lists of entries
- calendardisplay.php « handles rendering of data into calendars (not well refined yet)
- graphdisplay.php « handles rendering of data into graphs (not well refined yet)
- extract.php « the data extraction layer, for retrieving data from any dataset, and functions for handling it
- readelements.php « handles receiving data from a form submission and saving it to the DB
- functions.php « a giant set of functions for doing different operations, some tiny, some huge
- templates
- admin « where all the page templates are for the backend admin pages
- screens
- Anari « contains default templates, and folders with numeric names corresponding to screen id numbers. These numeric folders contain any custom templates used for each screen.
- default « where the default templates are for lists and forms in the Anari theme
- form « templates for rendering forms when no screen is in effect. Also used for legacy form screens from before Formulize 7 (all form screens are multipage now)
- listOfEntries « templates for rendering lists of entries
- toptemplate.php « the template for rendering contents above the list of entries, ie: buttons, navigation aids, etc
- openlisttemplate.php « the template for content that opens the list of entries, ie: <table> etc. Also contains any items that occur only at the top of the list, but after the list container
- listtemplate.php « the template that renders each item in the list
- closelisttemplate.php « the template the closes the list
- bottomtemplate.php « the template that renders all content below the list
- multiPage « templates for rendering form screens
- toptemplate.php « the template for rendering the title, tab navigation, and any other details that appear above the form elements
- elementcontainero.php « the template that opens the DOM element that contains a form element (ie: a <tr> or <div> etc)
- elementtemplate1.php « the template that is used to render form elements when the form is using a single column layout
- elementtemplate2.php « the template that is used to render form elements when the form is using a two column layout (and this layout should collapse responsively into a single column layout if the form is rendered on a narrow screen)
- elementcontainerc.php « the template that closes the DOM element that contains a form element (ie: a </tr> or </div> etc)
- bottomtemplate.php « the template that renders the page below the main list of entries
- default « where the default templates are for lists and forms in the Anari theme
- default « where the general default templates are for lists and forms if there are none for the active theme
- Anari « contains default templates, and folders with numeric names corresponding to screen id numbers. These numeric folders contain any custom templates used for each screen.
- formulize « where the magic happens
- themes
- Anari
- theme.html « the main page template used for all pages in the website
- css
- style.css « the css file containing all the site-wide styles for the website
- Anari
Code flow
-
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).