Skip to main content

Module Migration Guide

This guide provides useful information about migrating your custom modules in order to keep them compatible with new HumHub versions. You should keep your modules up-to-date by removing deprecations and align code breaking changes of the platform and ideally test your modules against new HumHub version. Also keep in mind to align the minVersion of your module when using new features.

You can execute code for specific versions by using the version_compare function as:

if (version_compare(Yii::$app->version, '1.3', '=>')) {
// Use some 1.3+ features here
} else {
// Compatibility code for older versions

Migrate from 1.9 to 1.10

  • Removed Followable behavior methods getFollowingCount(), getFollowingObjects($query), getFollowers()
  • File versioning support has been introduced. File contents are now immutable. See File module documentation.
  • Removed user's name encoding in UserPicker

Migrate from 1.8 to 1.9

  • New Ajax Validator for ControllerAccess to force Ajax requests.
  • New setting "Default Timezone" Yii::$app->settings->get('defaultTimeZone') instead of the deprecated setting "Server Timezone" Yii::$app->settings->get('timeZone').
  • CodeMirror is now directly bundled with HumHub core from humhub\modules\ui\form\widgets\CodeMirrorInputWidget and can be applied to any textarea field with code like $form->field($model, 'textareaFieldName')->widget(CodeMirrorInputWidget::class).
  • Updated to PHPUnit 8.5 (#4757)

Migrate from 1.7 to 1.8

  • AdminMenu: A visibility must always be specified for custom menu entries. See example code.
  • User Account "Security" page renamed to "Permissions". (Changed action id and views)
  • Removed unused legacy widget modules/admin/widgets/UserSettingMenu.php
  • Groups can now have multiple default spaces. The Group::getSpace() method has been removed and replaced by Group::getGroupSpaces().

Richtext changes

In 1.8 we've introduced some changes in the Richtext API by introducing converter classes as:

  • RichTextToShortTextConverter: Used to convert Richtext to a html preview without text formatting.
  • RichTextToHtmlTextConverter: Used to convert Richtext to plain html e.g. in html mails
  • RichTextToMarkdownTextConverter: Used to convert Richtext to plain markdown without HumHub richtext extensions
  • RichTextToPlainTextConverter: Used to convert Richtext to plain text e.g. for text mails

Richtext conversion can also be achieved by the RichText::convert() function.

In this step we've added the following deprecations:

  • humhub\libs\Markdown is deprecated in favor of RichTextToHtmlConverter or RichText::convert()
  • humhub\libs\MarkdownPreview is deprecated in favor of RichTextToShortTextConverter or RichText::convert()
  • RichText:$minimal option was deprecated in favor of RichTextToShortTextConverter or RichText::convert() should be used for previews.
  • RichText:$maxLength option was deprecated, Richtext content should not be cut anymore, only RichTextToShortTextConverter should be used for previews.
  • ProsemirrorRichText::parseOutput() was used for additional Richtext extensions and should be replaced with a RichTextExtension implementation
  • ProsemirrorRichText::scanLinkExtension() is deprecated in favor of a RichTextExtension implementation
  • ProsemirrorRichText::replaceLinkExtension() is deprecated in favor of a RichTextExtension implementation

Richtext compatibility parser

Prior to this update the Richtext compatibility parser responsible for supporting richtext syntax of HumHub < 1.3 was active by default and could not easily be deactivated. In HumHub 1.8 this parser is deactivated for new installations and can be deactivated for existing installation, which do not need to support richtext created with HumHub < 1.3. The compatibility parser can be deactivated in order to improve performance by configuration file:

return [
'modules' => [
'content' => [
'richtextCompatMode' => false

Migrate from 1.6 to 1.7

New WallEnry Layouts

The new humhub\modules\content\widgets\stream\StreamEntryWidget classes replaces the old humhub\modules\content\widgets\WallEntry.
Beside the StreamEntryWidget, which is now the base class for all kinds of stream entries, there are two different widget types for wall streams (e.g. Dashboard, Space, Profile) the humhub\modules\content\widgets\stream\WallStreamEntryWidget and humhub\modules\content\widgets\stream\WallStreamModuleEntryWidget.


The WallStreamEntryWidget renders a similar as the current but enhanced stream entry layout with the user image and user name in the head section of the stream entry. This widget type should be used for content which emphasizes the author of the content and contains mainly personal (not collaborative) content.


The WallStreamModuleEntryWidget on the other hand is new and does not emphasize the user, but instead the content type and the content title. This widget should be used for content types in which the author is not that important as for example a wiki or other collaborative content.


The old humhub\modules\content\widgets\WallEntry widget was deprecated and modules should be migrated as soon as possible.

Old Post WallEntry:

namespace humhub\modules\post\widgets;

class WallEntry extends \humhub\modules\content\widgets\WallEntry
public $editRoute = '/post/post/edit';

public function run()
return $this->render('wallEntry', ['post' => $this->contentObject, 'justEdited' => $this->justEdited]);


New Post WallEntry:

use humhub\modules\content\widgets\stream\WallStreamEntryWidget;

class WallEntry extends WallStreamEntryWidget
public $editRoute = '/post/post/edit';

protected function renderContent()
return $this->render('wallEntry', ['post' => $this->model, 'justEdited' => $this->renderOptions->isJustEdited()]);

Example of WallStreamModuleEntryWidget:

use humhub\modules\content\widgets\stream\WallStreamModuleEntryWidget;

class WallEntry extends WallStreamModuleEntryWidget
public $editRoute = '/mymodule/mycontent/edit';

protected function renderContent()
return $this->render('wallEntry', ['model' => $this->model, 'renderOptions' => $this->renderOptions]);

protected function getIcon()
// By default we do not have to define an icon unless we want to overwrite the default ContentActiveRecord::$icon
return 'tasks';

protected function getTitle()
return $this->model->title;
Integration of other ContentTags

In the old WallEntry widget all content labels returned by ContentActiveRecord::getLabels() as topics and content specific badges were added to the head section of the stream entry. In the new layout the topics are the only content tags which are automatically rendered. Content specific tags now need to be manually integrated into the body part of the stream entry.


  • Closed Poll
  • Task state
  • Wiki category
  • Canceled event
  • Calendar Type

Sub classes of WallStreamEntryWidget need to implement the renderContent instead of run.


In the old WallEntry::getContextMenu() was renamed to WallStreamEntryWidget::getControlsMenuEntries() widget class context entries should be added as follows

public function getContextMenu()
$result = parent::getContextMenu();
$this->addControl($result, [SomeLink::class, ['content' => $this->contentObject], ['sortOrder' => 200]]);
return $result;

In the new WallStreamEntryWidget class you should directly add the widget or array definition to the result array e.g.:

public function getControlsMenuEntries()
$result = parent::getContextMenu();
$result[] = [SomeLink::class, ['content' => $this->contentObject], ['sortOrder' => 200]];
return $result;

The WallEntry::controlsOptions is not available anymore replace:

  • $controlsOptions['prevent'] with $this->renderOptions->disableControlsEntry()
  • $controlsOptions['add'] with simple $result[] = $linkdefinition

Within your WallStreamEntryWidget you now can use WallStreamEntryOptions to change the behavior or appearance of your WallStreamEntryWidget depending on the view context.

Here are some usecases:

  • We may want to disable some menu items in the modal or search view since they do not work or are not expected in this context
  • You want to display the whole content of a post (without read more) in the single stream entry view, but not in the container or dashboard stream
  • A dashboard stream entry adds some additional information as the target container while this information is not rendered in container streams.
  • We may want to disable stream entry addons and most of the controls on archived content
  • We want to implement a custom stream and overwrite the default widget class bound to the ContentActiveRecord
  • Content which was edited can be highlighted
  • You want to disable the default edit link, and replace it with your own implementation

Deprecations in stream and stream action logic

The following deprecations were added to the Stream class and moved to a humhub\modules\stream\actions\LegacyStreamTrait

  • humhub\modules\stream\actions\Stream::$mode (which is not in use since 1.5)
  • humhub\modules\stream\actions\Stream::$from was replaced with StreamQuery::from (which is not new the old property is just deprecated and was not in use)
  • humhub\modules\stream\actions\Stream::$to was replaced with StreamQuery::to (which is not new the old property is just deprecated and was not in use)
  • humhub\modules\stream\actions\Stream::$activeQuery - StreamQuery::query() should be used to access activeQuery directly
  • humhub\modules\stream\actions\Stream::getContentResultEntry() was deprecated and replaced with StreamEntryResponse::asArray() or StreamEntryResponse::asJson() should be used
  • humhub\modules\stream\actions\Stream::renderEntry() was deprecated and replaced with StreamEntryWidget::renderEntry()
  • humhub\modules\stream\actions\Stream::setupCriteria() and setupFilters() are deprecated, in order to set filters or manipulate the query you should overwrite Stream::beforeApplyFilters()or Stream::afterApplyFilters()
  • humhub\modules\stream\actions\Stream::MODE_NORMAL, Stream::MODE_ACTIVITY, Stream::FROM_DASHBOARD are replaced with StreamEntryOptions::viewMode (only the FROM_DASHBOARD was active anyways)
  • humhub\modules\content\components\ContentActiveRecord::getWallOut() was replaced with StreamEntryWidget::renderEntry()

Other 1.7 Migration Issues

  • The sort order for Menu Entries or BaseStack (e.g. Sidebars) classes should now be set to a maximum of 10000. If no sort order is specified, the sort order is set to 9000.

  • Classes (LDAP, HTTP Client) from the deprecated Zend Framework have been replaced by the compatible Laminas Framework. There is a compatibility layer but classes should be replaced up to HumHub 1.8.

  • Removed humhub\modules\space\widgets\Picker which is deprecated since v1.2.

  • Removed class humhub\widgets\RichtextField which is deprecated since v1.4.

Migrate from 1.5 to 1.6

No breaking changes.

Migrate from 1.4 to 1.5

Asset Management

In HumHub 1.5 the loading of core assets was optimized by splitting the main humhub\assets\AppAsset into two separate bundles. The old AppAsset, which was reduced to only a few core scripts and stylesheets and a new humhub\assets\CoreBundleAsset. The CoreBundleAsset contains other core dependencies which are not as essential and will be loaded with a defer script attribute, which means those assets are not available immediately within the html body while not blocking the site rendering process.

You'll have to follow one of the migration options described below in case your scripts depend on one of the following assets:

  • JqueryColorAsset,
  • JqueryHighlightAsset,
  • JqueryAutosizeAsset,
  • Select2Asset,
  • Select2BootstrapAsset,
  • JqueryWidgetAsset,
  • NProgressAsset,
  • JqueryNiceScrollAsset,
  • BlueimpFileUploadAsset,
  • BlueimpGalleryAsset,
  • ClipboardJsAsset,
  • ImagesLoadedAsset,
  • HighlightJsAsset,
  • SwipedEventsAssets,
  • CoreExtensionAsset,
    • js/humhub/humhub.ui.modal.js,
    • js/humhub/humhub.ui.form.elements.js,
    • js/humhub/humhub.ui.form.js,
    • js/humhub/humhub.ui.showMore.js,
    • js/humhub/humhub.ui.panel.js,
    • js/humhub/humhub.ui.progress.js,
    • js/humhub/,
    • js/humhub/humhub.ui.picker.js,
    • js/humhub/humhub.oembed.js,
    • js/humhub/,
    • js/humhub/humhub.client.pjax.js,
  • ProsemirrorEditorAsset,
  • ProseMirrorRichTextAsset,
  • UserAsset,
  • LiveAsset,
  • NotificationAsset,
  • ContentAsset,
  • ContentContainerAsset,
  • UserPickerAsset,
  • FileAsset,
  • PostAsset,
  • SpaceAsset,
  • TopicAsset,
  • FilterAsset,
  • CommentAsset,
  • LikeAsset,
  • StreamAsset,
  • ActivityAsset,
  • SpaceChooserAsset

It is recommended to migrate to deferred scripts loading even if you don't depend on the CoreBundleAssets.


In case your scripts are exclusively loaded by ajax for example within the wall stream, you don't have to care about the CoreBundleAsset dependency.

AssetBundle Migration

If your AssetBundle depends on the CoreAssetBundle you'll need to add deferred script loading to your scripts.

HumHub >=1.5 only migration:

If you don't plant to stay compatible with older HumHub versions you can manage the script loading by extending the humhub\components\assets\AssetBundle, which will make use of deferred script loading by default. Don't forget to update "humhub": {"minVersion": "1.5"} within your module.json.

use humhub\components\assets\AssetBundle;

class MyAssetBundle extends AssetBundle

The new humhub\components\assets\AssetBundle provides some new useful features and default settings besides the script loading management.

HumHub < 1.5 compatibility

In case you want to stay compatible with older HumHub versions, you can enable the defer script loading by setting a $defer property as in the following example. This property will simply be ignored in HumHub versions < 1.5.

use yii\web\AssetBundle;

class MyAssetBundle extends AssetBundle
// Activate deferred script loading (this prop
public $defer = true;


The following example enables deferred script loading even on HumHub versions < 1.5.

use yii\web\AssetBundle;
use yii\web\View;

class CoreBundleAsset extends AssetBundle

public $jsOptions = [
// Make sure scripts are added after CoreBundleAsset
'position' => View::POS_BEGIN,
'defer' => 'defer'

Script Migration

The following options are available to migrate non deferred scripts as for example inline scripts which are dependent on CoreAssetBundle.

Use of humhub:ready listener

The humhub:ready event is triggered once all modules are loaded and initialized.

$(document).one('humhub:ready', function(event, isPjax, humhub) {
var stream = humhub.require('stream');
// do stuff...

You can also define modules within a humhub:ready event handler, this will also ensure all dependencies are available and may be useful when working with inline scripts.

$(document).one('humhub:ready', function(event) {    
humhub.module('myModule', function(module, require) {
var stream = require('stream');
// do stuff...

By using one instead of on we make sure our handler is only executed once, otherwise the handler would be executed on each pjax page transition.

HumHub module module init()

The init function of your HumHub javascript module will always be called once all scripts are available.

// myModule.js
humhub.module('myModule', function(module, require) {

* Outside of init some modules may not be available, so make sure to follow one of the other migration options
* when using requiring a js module included in CoreAssetBundle.

init: function(isPjax) {
// All scripts are loaded and stream dependency is available
var Stream = require('stream').Stream;

Deactivate deferred script loading

If none of the above migration options makes you happy, you can disable the deferred script loading as follows:

Globally within config.php

return [
'components' => [
'assetManager' => [
'preventDefer' => true

Default lazy javascript module loading

In HumHub 1.5 modules required by humhub.require() will be fetched lazily by default, which means a module will be initialized by require() in case it has not been loaded yet. In HumHub <1.5 a lazy flag was required to be set in require e.g. require('moduleId', true). This behavior was introduced in order to be more tolerant regarding script loading order due to the core asset loading change. Since lazy loaded modules are rarely used on purpose a warning is logged to the console once a module was loaded lazily for troubleshooting.


Lazy module loading only works on real modules and not on exported classes:

// Can be required lazily and will be available in init at the latest
var stream = require('stream');

// Can not be required lazily and won't be available if the module was not loaded already
var Stream = require('stream.Stream');

Other changes

Some assets bundles were removed from the AppAsset, in case one of them is required in your custom module, you should register them manually or even better include them in your custom module since they probably will be removed in an upcoming release:


  • Removed legacy humhub\assets\PagedownConverterAsset from AppAsset
  • Removed legacy humhub\assets\JqueryCookieAsset from AppAsset
  • Removed legacy resources/file/fileuploader.js from AppAsset
  • Removed legacy resources/user/userpicker.js from AppAsset
  • Removed legacy js/humhub/legacy/jquery.loader.js from CoreApiAsset
  • Removed legacy js/humhub/legacy/app.js from CoreApiAsset
  • Removed legacy js/humhub/humhub.ui.markdown.js from CoreApiAsset
  • SocketIoAsset is only registered on demand
  • Deprecated humhub\modules\ui\form\widgets\MarkdownField in order to favor humhub\modules\content\widgets\richtext\RichTextField

Loaded on demand:

  • Removed humhub\assets\SocketIoAsset from AppAsset

Migrate from 1.3 to 1.4

CSP and Nonce support

Please test your modules against the security.strict.json rules and mention possible incompatibilities in your module description.

In order to support CSP nonces you should either completely avoid using inline scripts or use one of the techniques described in the Javascript Guide. Its furthermore recommended to avoid inline styles, as they may be restricted in the strict CSP rule in a future version as well.

The menu system has been revised, is mostly downward compatible, but the old API methods/views will be removed with the next HumHub 1.5 version.

Please adjust your module menus accordingly. More details can be found in the Menu chapter of the developer documentation.

Language codes

Following language codes has been changed.

If you're using any custom modules, please change the message directories accordingly.

Old language codeNew language code

Removed deprecated methods

The following deprecated method have been removed.

Content model -removed methods

  • canWrite()
  • canRead()
  • canDelete()
  • getSpace()
  • getUser()

Removed class

  • humhub\modules\space\modules\manage\widgets\Menu

Space class - removed methods

  • canInvite()
  • canShare()

Notification class - removed methods

  • getSpace()

Migrate from 1.2 to 1.3

New Stream Javascript API

In v1.3 we've reworked the Stream Javascript API. Please check the Javascript Stream documentation for more information.

ContentContainer Controller

The base controller attributes autoCheckContainerAccess and hideSidebar are not longer available.


Queue related classes has been moved into an own module humhub\modules\queue. The existing humhub\components\queue\ActiveJob is declared as deprecated and will be removed in 1.4.

Partial user deletion (Soft Delete)

Added new user status (User::SOFT_DELETED). You can find more information here: Users


Moved all form and field related widgets from humhub\widgets to humhub\modules\ui\form\widgets namespace. There is a compatibility layer for the 1.3 release.

Social Activities (Notification & Activities)

  • Added new 'requireOriginator' flag with default to true
  • Added new 'requireSoruce' flag with default to true


Removed Deprecated

  • formatterApp Application Component (Yii::$app->formatterApp)

New Deprecations

  • humhub\components\Theme.php -> humhub\modules\ui\view\components\Theme
  • humhub\components\View -> humhub\modules\ui\view\components\View
  • humhub\libs\ThemeHelper -> humhub\modules\ui\view\components\ThemeHelper
  • humhub\modules\content\widgets\richtext\HumHubRichText -> Compatibility class for the legacy rich-text, which was replaced with prosemirror richtext.
  • humhub\modules\content\widgets\richtext\HumHubRichTextEditor -> Compatibility class for the legacy rich-text, which was replaced with prosemirror richtext editor.
  • humhub\widgets\RichText -> humhub\modules\content\widgets\richtext\RichText
  • humhub\widgets\RichTextField -> humhub\modules\content\widgets\richtext\RichTextField
  • humhub\modules\user\models\Mentioning::parse() -> humhub\modules\content\widgets\richtext\RichText::processText()

We moved most of the humhub\widgets into the new ui core module as:

  • humhub\widgets\ActiveField
  • humhub\widgets\ActiveForm
  • humhub\widgets\BasePickerField
  • humhub\widgets\ColorPickerField
  • humhub\widgets\ContentTagDropDown
  • humhub\widgets\DatePicker
  • humhub\widgets\DurationPicker
  • humhub\widgets\InputWidget
  • humhub\widgets\MarkdownField
  • humhub\widgets\MarkdownFieldModals
  • humhub\widgets\MultiSelectField
  • humhub\widgets\TimePicker

Migrate from 1.1 to 1.2

Stream / Content Changes

The models WallEntry and Wall were removed. So all corresponding methods like getFirstWallEntryId() are not longer available. The stream handling is now handled directly by the Content model. Also all stream classes (widgets, actions) are moved into the humhub\modules\stream package.

File module changes

Please refer the new File Handling documentation section for more details regarding the new file management API.

  • Deprecated widgets:
    • humhub\modules\user\widgets\UserPicker (replaced with humhub\modules\user\widgets\UserPickerField)
    • humhub\modules\space\widgets\Picker (replaced with humhub\modules\space\widgets\SpackePickerField)
    • humhub\widgets\DataSaved (replaced with humhub\components\View::saved)
  • Removed Content models 'attachFileGuidsAfterSave' attribute and handling
  • Deprecated File model methods
    • \humhub\modules\file\models\File::attachPrecreated
    • \humhub\modules\file\models\File::getFilesOfObject
    • \humhub\modules\file\models\File::getStoredFilePath
    • \humhub\modules\file\models\File::getPreviewImageUrl
    • \humhub\modules\file\models\File::attachPrecreated
    • \humhub\modules\file\models\File::getFilename
    • \humhub\modules\file\models\File::getInfoArray
    • \humhub\modules\file\models\File::getMimeBaseType
    • \humhub\modules\file\models\File::getMimeSubType
    • \humhub\modules\file\models\File::getExtension
  • Removed configuration option 'showFilesWidgetBlacklist' use WallEntry showFiles attribute instead.
  • File models title attributes is not longer automatically populated with the filename when empty
  • Moved file upload capabilities (UploadedFile) from File model to FileUpload model
  • Moved file store content by attribute capabilities from File model to FileContent model
  • Created UploadAction/DownloadAction classes

Pjax + TopNavigation:


public $topMenuRoute = '/dashboard/dashboard';

within your controller for pjax topmenu support.

Migrate from 1.0 to 1.1

  • Dropped unused space attribute "website"

  • ContentContainer Model Changes

    • Removed canWrite method (now requires own implementation using permissions)
  • Content Model Changes

    • Removed space_id / user_id columns - added contentcontainer_id
    • Not longer validates content visibility (private/public) permissions
  • system_admin attribute in user table was removed see humhub\modules\user\models\User::isSystemAdmin

  • Renamed space header settings menu dropdown class from humhub\modules\space\modules\manage\widgets\Menu to humhub\modules\space\widgets\HeaderControlsMenu

  • Refactored settings system. see Settings Documentation for more details. Old settings api is still available in 1.1.x

  • Refactored user group system

  • New administration menu structure

Migrate from 0.20 to 1.0

Migrate from 0.12 to 0.20

Important: This release upgrades from Yii1 to Yii2 Framework!

This requires an extensive migration of all custom modules/themes. Find more details here: HumHub 0.20 Migration

Migrate from 0.11 to 0.12

  • Rewritten Search

Migrate from 0.10 to 0.11

No breaking changes.

  • Now handle ContentContainerController layouts, new option showSidebar
  • New ContentAddonController Class
  • New Wiki Parser / Editor Widget