October CMS 3.1 - Stable Release

Release Note 32

Version 3.1 of October CMS hallmarks the stable version of this major release. It can be safely used in production environments.

Table of Contents

New Storage Disks

The storage engine used by October CMS has been refactored to include separate disks for the media manager, upload service and dynamic resources (combiner, resizer). Please make sure you have this new configuration included in config/filesystems.php.

'uploads' => [
    'driver' => 'local',
    'root' => storage_path('app/uploads'),
    'url' => '/storage/app/uploads',
    'visibility' => 'public',
    'throw' => false,

'media' => [
    'driver' => 'local',
    'root' => storage_path('app/media'),
    'url' => '/storage/app/media',
    'visibility' => 'public',
    'throw' => false,

'resources' => [
    'driver' => 'local',
    'root' => storage_path('app/resources'),
    'url' => '/storage/app/resources',
    'visibility' => 'public',
    'throw' => false,

These disks should be configured accordingly if you are using a CDN or external driver for the storage. You may also remove the storage key from the config/system.php file. The following keys have been renamed:

Old Key New Key
system.storage.media.disk filesystems.disks.media.driver
system.storage.media.path filesystems.disks.media.url
system.storage.media.folder filesystems.disks.media.root
system.storage.media.thumb_folder media.thumb_folder
system.storage.resources.disk filesystems.disks.resources.driver
system.storage.resources.path filesystems.disks.resources.url
system.storage.resources.folder filesystems.disks.resources.root
system.storage.uploads.disk filesystems.disks.uploads.driver
system.storage.uploads.path filesystems.disks.uploads.url
system.storage.uploads.folder filesystems.disks.uploads.root
system.storage.uploads.ttl filesystems.disks.uploads.ttl

It is important to note that since there are 3 disks, it may require defining multiple disks with the same or similar configuration. The following example can be useful when using Amazon S3 or any other CDN provider. The root attribute can be used to specify a subfolder inside the same bucket (previously called folder). The url can specify a public URL endpoint for accessing the contents.

'uploads' => [
    'driver' => env('FILESYSTEM_DRIVER', 'local'),
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION', 'us-west-1'),
    'bucket' => env('AWS_BUCKET'),
    'endpoint' => env('AWS_ENDPOINT'),
    'root' => env('STORAGE_UPLOADS_PATH', storage_path('app/uploads')),
    'url' => env('STORAGE_UPLOADS_URL', '/storage/app/uploads'),
    'visibility' => 'public',
    'throw' => false,
    'ttl' => 3600,

'media' => [
    'driver' => env('FILESYSTEM_DRIVER', 'local'),
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION', 'us-west-1'),
    'bucket' => env('AWS_BUCKET'),
    'endpoint' => env('AWS_ENDPOINT'),
    'root' => env('STORAGE_MEDIA_PATH', storage_path('app/media')),
    'url' => env('STORAGE_MEDIA_URL', '/storage/app/media'),
    'visibility' => 'public',
    'throw' => false,

'resources' => [
    'driver' => env('FILESYSTEM_DRIVER', 'local'),
    'key' => env('AWS_ACCESS_KEY_ID'),
    'secret' => env('AWS_SECRET_ACCESS_KEY'),
    'region' => env('AWS_DEFAULT_REGION', 'us-west-1'),
    'bucket' => env('AWS_BUCKET'),
    'endpoint' => env('AWS_ENDPOINT'),
    'root' => env('STORAGE_RESOURCES_PATH', storage_path('app/resources')),
    'url' => env('STORAGE_RESOURCES_URL', '/storage/app/resources'),
    'visibility' => 'public',
    'throw' => false,

Web Installer and One-click Updates

The web installation wizard has been rebuilt to support the latest version of October CMS, including the ability to update the system using one-click updates. It offers the same great experience and is now powered by Composer.

You can find the web installer at the GitHub repo and the one-click updates are available via the system settings in the admin panel.


Drivers Plugin Retired

The October Drivers plugin has been retired in v3.0 onwards. If you have this plugin installed, please uninstall it as part of your upgrade process. The documentation now refers to the individual composer packages that should be installed instead, for example, in the media manager documentation it is recommended to require the league/flysystem-aws-s3-v3 package for AWS integration.

composer require league/flysystem-aws-s3-v3 "^3.0"

Boostrap 5 Upgrade

The admin panel has been upgraded to Bootstrap 5 with many newly added features available to use. In previous versions an internal fork of Bootstrap 3 was used and this is replaced with native Bootstrap 5 support.

Most legacy classes have been kept to maintain backwards compatibility support with previous versions of October CMS plugins and themes. However, some changes may be required, learn more about the upgrade process in the Upgrading Backend Panel to Bootstrap 5 article.

Multsite Functionality

October CMS now ships with an optional feature called multisite; the next tier above building multilingual websites. There is a new settings area called Manage Sites where you can configure multiple sites per installation. Depending on the URL or a website selected by a visitor, we can display:

  • Content variations
  • Completely different content
  • Same content in different languages
  • Different look for websites

When multiple sites are detected, a site picker will appear in the admin panel to switch sites. The RainLab Translate has been rebuilt to include support for multisite and there is a new Multisite trait that can be used as an implementation.

class User extends Model
    use \October\Rain\Database\Traits\Multisite;

    // ...

View the multisite and database traits documentation to learn more.

Note: For multi tenanted applications, we recommend consulting with your DevOps team to handle this at the web server level for the best performance and security.

New AJAX Framework

October CMS now ships with a new AJAX framework that is built from the ground up using Vanilla JavaScript, removing the need to include jQuery in your themes. The new framework is a drop-in replacement for the old one and supports the previous syntax if jQuery is detected.

// jQuery API
$.request('onSomething', { data: someVar });

// Vanilla JS API (New)
oc.ajax('onSomething', { data: someVar });

// jQuery API
$('.some-element').request('onSomething', { data: someVar });

// Vanilla JS API (New)
oc.request('.some-element', 'onSomething', { data: someVar });

There is only one noticable breaking change to the error function signature. The argument order has changed and this is an intentional break to make the API more consistent. Also - the textStatus (provided by jQuery) has been replaced with the HTTP response code.

Old signature:

success: function(data, textStatus, jqXHR)
complete: function(data, textStatus, jqXHR)
error: function(jqXHR, textStatus, errorThrown)

New signature:

success: function(data, responseCode, xhr)
complete: function(data, responseCode, xhr)
error: function(data, responseCode, xhr)

The method signatures are now consistent across the board. The code for the AJAX Framework is public and can be found at the GitHub repo.

Turbo Routing

The Turbo Router is an implementation of PJAX (push state and AJAX) that uses complementary techniques to dramatically reduce the amount of JavaScript needed to create modern websites. PJAX is now included in the frontend and backend areas by default and is a step forward in modernizing the platform.

You can include the turbo router by including turbo as an attribute in the {% framework %} tag.

{% framework extras turbo %}

The backend area uses the turbo router by default. If there are affected plugins, you may disable it in the backend with the backend.turbo_router setting.

// config/backend.php
'turbo_router' => false,

Plugin developers can disable PJAX on specific controllers by including the turboVisitControl property.

 * @var bool turboVisitControl forces a reload
public $turboVisitControl = 'disable';

We encourage you to learn more about introducing PJAX support by reading the documentation.

Permission Changes

Permission codes support a nested structure to provide a cleaner interface when selecting permissions. To nest a permission code the "dot" value must be a direct descendant of its parent and unlimited nesting is supported.

In the following example, the manage_entries permission must be granted for the manage_entries.create and manage_entries.publish codes to become available. Visually it is represented like this:

├── manage_entries
|   ├── manage_entries.create
|   └── manage_entries.publish
└── delete_entries

The following permissions codes have been migrated to the new system:

Old Permission New Permission
system.manage_updates general.backend.perform_updates
backend.access_dashboard dashboard
backend.manage_default_dashboard dashboard.defaults
media.manage_media media.library
editor.access_editor editor
tailor.manage_blueprints editor.tailor_blueprints
cms.manage_content editor.cms_content
cms.manage_assets editor.cms_assets
cms.manage_pages editor.cms_pages
cms.manage_layouts editor.cms_layouts
cms.manage_partials editor.cms_partials
cms.manage_themes cms.themes
cms.manage_theme_options cms.theme_customize
backend.manage_users admins.manage
system.manage_mail_templates mail.templates
system.manage_mail_settings mail.settings
backend.manage_preferences preferences
backend.manage_editor preferences.code_editor
backend.manage_branding settings.customize_backend
system.access_logs utilities.logs

Role Hierarchy

A new role hierarchy system has been introduced where each role is assigned a ranked position in the backend panel. This allows a basic organisational structure to be established where users can only manage roles lower than their own role.

In the following example, the Senior Editor can manage all the users, outranking Staff Writer and Fact Checker roles. Whereas, the Fact Checker role cannot see users or manage permissions above them, in the Staff Writer and Senior Editor roles.

  1. Senior Editor
  2. Staff Writer
  3. Fact Checker

If the Manage Admins → Manage Roles permission is granted, users can manage their own users, permissions and roles existing below their current role.

This is the end of the document, you may read the announcement blog post or visit the changelog for more information.

comments powered by Disqus