Skip to content

Releases: jbroadway/elefant


@lux lux
Choose a tag to compare


  • Added optional default value to Cache::get(), supported by Redis and filesystem backends
  • Added conf/workers.php worker definition file and ./elefant start-workers command to start them
  • Added make worker to build a new elefant-worker Docker container image
  • Added example background worker script in apps/jobqueue/handlers/worker.php
  • Added Beanstalkd and a worker container to the docker compose setup
  • Converted docker compose setup to use MariaDB since it has an arm64-compatible image
  • Removed explicit container names from docker compose for easier multi-site use

Bug fixes

  • Updated CodeMirror dependency to fix Github security alert
  • Fixed static variable reference in Model::get() error handling
  • Defined $i18n->default so it's explicit, instead of implicit from correct config
  • Added check for SubfolderException class existence to remove warning in $controller->quit()
  • Fixed internal variable name in $controller->status_code()
  • Fixed Template tests for recent addition of $tpl->default_filter and optional 3rd $label parameter
  • Added Apache headers module to fix access to the files folder
  • Fixed end quote parsing error in blog\CsvParser


@lux lux
Choose a tag to compare

Column layouts

This feature builds on the recent improvements to the blocks/group handler and adds the ability to define column layouts for each content row when row=on is set.

To try it out, add the following to your layout template:

{! blocks/group?wildcard=[id]-*&rows=on !}

This tag turns a page into an expandable set of rows of content blocks, which can now also contain up to 5 columns of content.

You'll see a new Content Layout button next to the up/down arrows in the block edit buttons. The buttons in the first column now control the properties for the entire row, and each column now has its own edit button too.

Screen Shot 2021-01-07 at 9 21 58 PM

When you click this new button, or when you click the Add Block button to add another row of content, you'll be shown the following options for content layouts:

Screen Shot 2021-01-07 at 9 12 18 PM

The layout can also be modified through the block add/edit forms sidebar:

Screen Shot 2021-01-07 at 9 15 11 PM

And finally, you can tab between the rows just above the wysiwyg editor, so you can edit an entire row from the same form:

Screen Shot 2021-01-07 at 9 16 31 PM

Docker support

Elefant now includes Docker configurations for building production and development containers, as well as a docker-compose file for spinning up a complete development environment in a single command which includes a MySQL database and Redis-backed caching.

To build a production container from a fresh clone of the Elefant repository, run:

$ make build

This will build a container named elefant. Similarly, you can build a development container via:

$ make dev

This will build a container named elefant-dev.

To spin up a development environment (after running make dev), run:

$ make run

And to shut it down, run:

$ make down

Take a look at the included docker-compose.yml and .docker/* files for more info.

Other improvements

  • Added ELEFANT_DEFAULT_PASS environment variable for ./elefant install command line installer
  • When you change the ID of a page that uses blocks/group as shown above, Elefant will update the block IDs so they don't become unlinked from the page
  • You can now load scripts asynchronously via $page->add_script ('/apps/myapp/js/script.js', 'async')
  • Updated CSRF validation to use sha256 and to use separate expiring tokens per request URI
  • Added User::error() to get the underlying reason for an authentication failure (e.g.,incorrect credentials, too many tries, database error)
  • Added pretty printing of JSON output in ./elefant api/get and ./elefant api/post command output
  • Added setting to opt-out of FLoC tracking under Site Settings, with the opt-out enabled by default
  • Added |comma filter to template variables, which outputs the value followed by a comma only if the value isn't empty

Bug fixes

  • Ensure block list in blocks/group is always an array to prevent errors
  • Auto-update wildcard block IDs when page IDs change
  • Fixed jGrowl's missing source map
  • Fixed error in ./elefant permissions command due to missing folder
  • Remove uploaded files from cache after import in blog app (Wordpress, Blogger, CSV)
  • File manager strips .php, .phtml, and .ht* files from unzipped folders for improved security
  • Prevent using base64 encoding to bypass function filter in designer app (e.g., {{base64_decode('cGhwaW5mbw==')()}})



  • Added Envconf as Appconf wrapper that checks for the existence of environment variables
  • Added envconf() wrapper around conf() that also checks for the existence of environment variables
  • Added Model::prefetch_field($id_list, $fieldname) to reduce database calls on repeat uses of Model::field()
  • Added exception handling to Redis cache connection failures
  • Added example setup of blocks stylesheet in the default theme under layouts/minimal/blocks.css

Bug fixes

  • Fixed forms not submitting when skip_if_empty is specified but the field isn't found in the HTML of the form


@lux lux
Choose a tag to compare

Introducing JobQueue

This update adds a new JobQueue class which is powered by Pheanstalk/Beanstalkd. This makes it very easy to setup background workers and send tasks to them for processing.


To set it up, install Beanstalkd via your package manager of choice (apt/yum/brew/port), for example:

$ apt install beanstalkd

Next, after upgrading Elefant to 2.2.4, run Composer update from the root directory of your website to install the Pheanstalk library:

$ cd /path/to/www && composer update

Lastly, edit the [JobQueue] settings in your conf/config.php file to point to your Beanstalkd server:


backend = beanstalkd
host =
port = 11300


Sending a job to be done by a background worker is as easy as:

JobQueue::enqueue ('tube-name', ['data' => '...']);

Writing a worker in Elefant looks like this:

<?php // apps/myapp/handlers/worker.php

if (! $this->cli) exit;

$page->layout = false;

$worker = JobQueue::worker ();

$worker->watch ('tube-name');

while ($job = $worker->reserve ()) {
    $data = json_decode ($job->getData ());

    // Process job with $data

    $worker->delete ($job);

The above worker can be run via php index.php myapp/worker and can be initialized using your system scheduler, such as systemd.

Note that workers can be written in any language that connects to Beanstalkd and listens for jobs to process.

Other improvements

  • Added User::require_verification() which extends User::require_login() to require email verification too
  • Added Auto-include Composer autoloader to Site Settings form so you no longer need to include it manually in a bootstrap.php file

Bug fixes

  • Fixed blog post slugs changing back to their default values
  • Fixed upgrades missing schema changes for in-between versions


  • Added $this->get_params() method to Restful for easier input parameter parsing and validation
  • Added ability to select from custom CSS styles for blocks/group rows 1
  • Marked all Elefant-related cookies with SameSite=Lax
  • Changed $cache->delete() to use unlink() for async deletions on newer versions of phpredis
  • Improved display and usability of tables in the wysiwyg editor
  • Fixed MySQL error at text field with default value
  • Fixed custom site styles affecting the Elefant toolbar heading colours and embedded button styles

1. The block editor first looks for a layouts/your-theme/blocks.css file, otherwise it reads all layouts/your-theme/*.css files, and finds all styles using the form .block-outer.custom-class-name. It then turns all unique custom classes found into selectable style options in a dropdown list.


@lux lux
Choose a tag to compare
  • Changed default theme to encourage shorter form of {! blocks !} tag use in layouts/minimal/inc/body.html
  • Fixed error in blog post preview if thumbnail isn't set
  • Fixed the version numbers in the installer that caused upgrade notices to appear incorrectly


@lux lux
Choose a tag to compare
  • Content Blocks:
    • Updated add/edit block forms to match page and blog forms
    • Added background image field to blocks
    • Added background image support to {! blocks/group !} helper
    • Added "Blocks: Group" to the Dynamic Objects menu so blocks can be embedded into any page or blog post
    • Added wildcard and rows parameters to blocks/group helper (usage: {! blocks/group?wildcard=[id]-*&rows=on !} which outputs all blocks with the pattern $page->id . '-*' as full-width editable blocks, in ascending order by block ID)
    • When rows is set, blocks can now be reordered on the page with up/down arrows
    • Fixed deleting a block not redirecting back to the page it was on
  • Social sharing
    • Added default thumbnail setting to Site Settings which is used in Open Graph and Twitter Card meta tags
    • Blog homepage now also sets Open Graph and Twitter Card meta tags
  • Usability
    • Added a search bar to the file manager which does a case-insensitive recursive search for any matching file or folder names.
    • Added page IDs to the navigation admin page so it's easier to distinguish between similarly-named pages when editing your site navigation
    • Added file names to the file browser dialog window so it's easier to distinguish between similar images when making a selection
    • Increased the size of the file browser dialog window and other usability improvements
    • Added Alt+E quick key to toggle the admin toolbar open and closed
    • Updated Google Fonts link in default theme to support https
  • Framework
    • Added opcache.preload support for speeding up websites on PHP 7.4+ via a new preload.php in the project root
    • Added select(), reset() and fields() methods to base Model class for more flexible query building
    • Added $_json_flags property to ExtendedModel for specifying json_encode() flags when encoding extended model data
    • Improved error checking in DB::shift() method
    • Added ability to override Template's default template filter via the $default_filter property which defaults to Template::sanitize
    • Added ability to defer included scripts via $page->add_script ('/path/to/script.js', 'defer')
    • Fixed deprecation warnings in markdown parser in PHP 7.4


@lux lux
Choose a tag to compare
  • Redesigned web page and blog post edit forms
  • Added thumbnail field to web pages to match blog posts
  • Added site-wide default thumbnail setting
  • Added editable permalink, meta description and keywords to blog posts
  • Automatically adds Open Graph and Twitter card tags to web pages
  • Updated CSV importer with keywords and description fields
  • Added $lock_level parameter to Model() for exclusive or shared locks
  • Fixed 'Back to Edit Mode' icon
  • Added Model->where_in('key', []) convenience method
  • Updated emojionearea to latest version (3.4.1) and added integrity check
  • Updated twemoji to latest version (12.1.5) and added integrity check
  • Updated pager to support larger numbers
  • Removed the need for the PHP calendar extension in the blog app
  • Improved blog archive queries
  • Generalized CSS for admin edit forms to improve consistency across forms
  • Added PHP 7.4 to travis-ci config and retired versions below 7.2
  • Added ./elefant api/get and api/post commands for easier API endpoint testing
  • Fixed API changes in embedded file browser
  • Allow dots in file name validator
  • Fixed console error when cancelling file rename or deletion
  • Using hash_equals() for passwords
  • Improved version history with titles and links back to edit forms
  • Fixed group by error in version history in newer versions of MySQL
  • Log API errors to the console for easier debugging
  • Made read-only /api/v1/* endpoints public so Elefant can be used as a headless CMS
  • Added issue date and expiry of API tokens without deletion via ./elefant api/expire-token <token>
  • Reduced the number of database queries used in the admin toolbar
  • Added lib to restrictions in sample nginx.conf
  • Removed deprecated methods used in FrontController for backwards compatibility
  • Ensure zlib compression is off in cli usage
  • Improved exception handling in cli usage
  • Improved redirections on saving pages and blog posts
  • Removed outdated version of jQuery
  • Admin toolbar requires a click to open now, to prevent it getting in the way
  • Added confirmation for overwriting existing files
  • Added button to clear existing thumbnails


@lux lux
Choose a tag to compare
  • "Images: Before/After" option was added to Dynamic Objects, powered by BeerSlider
  • Added Model::delete() method to build delete statements using Model::query() chains
  • Added webfeeds cover image to blog RSS output
  • Consistency fix for +() characters in HMAC auth, since some clients encode differently
  • Updated tests for PHPUnit 8
  • Updated URLify plugin
  • Record error to console if a visible notice isn't present for a form validation error
  • Added subresource integrity parameters to Page::add_script() and Page::add_style() to set integrity and crossorigin attributes
  • Removed references to Aviary editor and Persona auth
  • Added JSON Feed support to the blog
  • Added Media RSS support to the blog
  • Added SameSite support for CSRF protection for PHP 7.3+ users
  • Added Form::failed() convenience method
  • Only load lib/vendor/autoload.php if it exists
  • Deny all requests to /lib/*
  • Switched file manager endpoints to passing file parameter explicitly instead of inferring from the path


@lux lux
Choose a tag to compare

Security update

Updated the Apache .htaccess settings and Nginx example configuration to more securely handle files uploaded through the file manager.

Note: Nginx users should copy the following new lines into their server{} block in their Nginx configuration and restart Nginx to apply the update:

location ~ ^/files/.*\.(?!(gif|jpe?g|png|mp4|pdf))$ {
	add_header Content-disposition "attachment";

It was also discovered that file extension limits weren't being verified when renaming files, which has been fixed too.

Search improvements

We've made some big improvements to the search bar for Web Pages, Blog Posts, and Accounts. This also affects Model::where_search(), improving other instances of it as well.

You can now use "quoted text" in searches to search for literal phrases that include spaces.

You can also use -word to omit words from your search. Combined, these improvements give users a lot more flexibility in how they can query their data.

Other improvements

  • Password recovery page can be overridden with a custom handler.
  • Added a new |absolutize template filter (usage: {url|absolutize}) to ensure URLs are absolute.
  • Added conf/envmap.php to map alternate environment variables and to Elefant's own.

Bug fixes

  • Fixed an issue deleting files.
  • Fixed empty searches in Model::where_search().
  • Fixed consistency of HMAC to prefer + instead of %20.
  • Fixed potential error in blog post parsing.