Skip to content

@jbroadway jbroadway released this Nov 19, 2020


  • 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
Assets 2

@lux lux released this Sep 27, 2020

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
Assets 2

@jbroadway jbroadway released this Aug 24, 2020

  • 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.

Assets 2

@lux lux released this Jul 11, 2020

  • 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
Assets 2

@lux lux released this Jul 1, 2020

  • 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
Assets 2

@lux lux released this May 30, 2020

  • 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
Assets 2

@lux lux released this Nov 10, 2019

  • "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
Assets 2

@lux lux released this Apr 7, 2019

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.
Assets 2

@jbroadway jbroadway released this Dec 9, 2018


  • I18n filters now accept DateTime objects in addition to date strings
  • Added Form::generate_csrf_token() for custom use cases
  • Minimal grid supports every column size increment of 5%
  • Image::resize() defaults to auto-detecting the correct format
  • Access control on WYSIWYG editor plugins so the editor can still be used by non-admins
  • Updated Google OAuth2 login support and added Google auth credentials to user settings form
  • Added admin/util/select-buttons helper to convert select boxes to button groups
  • Let users set jquery_source = Off to disable jQuery completely on the front-end
  • Force jQuery source to be local if admin
  • Admin toolbar and admin area usability improvements
  • Added admin/modal template for admin pages in frames
  • Upgraded URLify to version 1.1.2-stable
  • Upgraded Analog to version 1.0.11-stable

Bug fixes:

  • Fixed error marking file manager app upgraded
  • Fixed exception in admin toolbar template
  • Removed PHP 5.3 from travis-ci config, fixed PHPUnit issues on travis-ci
  • Fixed issue with dollar signs in some database passwords
  • Fixed warning on templates not always quoting array keys
Assets 2

@jbroadway jbroadway released this Sep 11, 2018

Security updates:

  • Fixed remote execution in file manager (#287)
  • Fixed remote execution in stylesheet editor (#286)


  • Added "Now" button next to date field in blog posts

Bug fixes:

  • Fixed open graph image dimension tags
Assets 2