Elefant, the refreshingly simple PHP CMS and web framework.
Cache::get()
, supported by Redis and filesystem backendsconf/workers.php
worker definition file and ./elefant start-workers
command to start themmake worker
to build a new elefant-worker
Docker container imageapps/jobqueue/handlers/worker.php
Model::get()
error handling$i18n->default
so it's explicit, instead of implicit from correct configSubfolderException
class existence to remove warning in $controller->quit()
$controller->status_code()
Template
tests for recent addition of $tpl->default_filter
and optional 3rd $label
parameterfiles
folderblog\CsvParser
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.
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:
The layout can also be modified through the block add/edit forms sidebar:
And finally, you can tab between the rows just above the wysiwyg editor, so you can edit an entire row from the same form:
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.
ELEFANT_DEFAULT_PASS
environment variable for ./elefant install
command line installerblocks/group
as shown above, Elefant will update the block IDs so they don't become unlinked from the page$page->add_script ('/apps/myapp/js/script.js', 'async')
User::error()
to get the underlying reason for an authentication failure (e.g.,incorrect credentials, too many tries, database error)./elefant api/get
and ./elefant api/post
command output|comma
filter to template variables, which outputs the value followed by a comma only if the value isn't empty./elefant permissions
command due to missing folder{{base64_decode('cGhwaW5mbw==')()}}
)envconf()
wrapper around conf()
that also checks for the existence of environment variablesModel::prefetch_field($id_list, $fieldname)
to reduce database calls on repeat uses of Model::field()
layouts/minimal/blocks.css
skip_if_empty
is specified but the field isn't found in the HTML of the formThis 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:
[JobQueue]
backend = beanstalkd
host = 127.0.0.1
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.
User::require_verification()
which extends User::require_login()
to require email verification tooAuto-include Composer autoloader
to Site Settings form so you no longer need to include it manually in a bootstrap.php
fileRestful
for easier input parameter parsing and validationblocks/group
rows 1
SameSite=Lax
unlink()
for async deletions on newer versions of phpredis1. 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.
{! blocks !}
tag use in layouts/minimal/inc/body.html
{! blocks/group !}
helperwildcard
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)rows
is set, blocks can now be reordered on the page with up/down arrowsAlt+E
quick key to toggle the admin toolbar open and closedopcache.preload
support for speeding up websites on PHP 7.4+ via a new preload.php
in the project rootselect()
, reset()
and fields()
methods to base Model
class for more flexible query building$_json_flags
property to ExtendedModel
for specifying json_encode()
flags when encoding extended model dataDB::shift()
methodTemplate
's default template filter via the $default_filter
property which defaults to Template::sanitize
$page->add_script ('/path/to/script.js', 'defer')
$lock_level
parameter to Model()
for exclusive or shared locksModel->where_in('key', [])
convenience method./elefant api/get
and api/post
commands for easier API endpoint testinghash_equals()
for passwords/api/v1/*
endpoints public so Elefant can be used as a headless CMS./elefant api/expire-token <token>
lib
to restrictions in sample nginx.confModel::delete()
method to build delete statements using Model::query()
chains+()
characters in HMAC auth, since some clients encode differentlyPage::add_script()
and Page::add_style()
to set integrity and crossorigin attributesForm::failed()
convenience methodlib/vendor/autoload.php
if it exists/lib/*
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.
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.
|absolutize
template filter (usage: {url|absolutize}
) to ensure URLs are absolute.Model::where_search()
.+
instead of %20
.