The content concept is a fundamental part of HumHub and allows the implementation of different types of content.
The core content module is responsible for managing the visibility and other content features which are described in the following section.

The ContentActiveRecord class serves as the base class for
every content type as for example Polls, Posts or Wiki pages. While the ContentActiveRecord implementation
describes the specific behavior of a content type, all ContentActiveRecord instances are related
to a Content record which holds general content data as:

visibility

originator

creation date

updater

update date

ContentContainer relation

The following section describes common configuration possibilities of ContentActiveRecord subclasses.

ContentActiveRecord::moduleId should always be set with the related module id of your content record.

ContentActiveRecord::autoFollow flag is used to determine whether or not the content originator should automatically follow
this content after creation. In case the originator should not receive notifications for e.g. likes or comments by default, this
flag should be set to false.

ContentActiveRecord::streamChannel specifies the main context in which this type of content is used.
Activity content entries for example make use of an own stream channel and therefore are not included in the default wall stream channel.
In case you just want to exclude your content from the wall stream, set the stream channel to null.
This setting can also be changed by model updates in order to exclude the content only if some conditions are met.
As with activities, this field can also be used to create own custom streams.

ContentActiveRecord::silentContentCreation can be set to false if you want to prevent the creation of ContentCreated
notifications and activities for this type of content. Note, those activity records are only created when inserting
the content record. Changing this setting afterwards won't have any effect.

Just like other ActiveRecordsContentActiveRecord
classes should be put under the models namespace of your module. Beside the basic ActiveRecord features as validation and attributeLabels
your ContentActiveRecord class should at least implement the following fields and methods:

moduleId - id of the related module

getContentName() - short name/type of content

getContentDescription() - returns a short description of the content instance used to preview the content for example in activities etc.

Provide a content container and attribute config. In this case the default content visibility of the related container
will be used. This is the most common way of initializing a new ContentActiveRecord.

new Post($space, ['message' => 'Some message'])

The following example provides an additional visibility setting in order to force a content visibility:

The content visibility specifies who will be allowed to view a content instance.
When instantiating a new ContentActiveRecord without a predefined visibility
the underlying content will adapt the default content visibility of its ContentContainerActiveRecord.

Private content will only be visible for Space Members (Space) and Friend Users (Profile).

Public content will be visible for everyone including guests if the guest mode is active.

The content visibility can be checked by calling isPublic() and isPrivate() on the Content instance.

// Returns all MyModels related to the given $space$models = MyModel::find()->contentContainer($space)->all();
// Returns all MyModels related to the given $space and readable by the current user$models = MyModel::find()->contentContainer($space)->readable()->all();
// Loads all MyModels of the current users member spaces$models = MyModel::find()->userRelated([ActiveQueryContent::USER_RELATED_SCOPE_SPACES])->all();
// Loads all readable MyModels of the current users spaces and also followed spaces$models = MyModel::find()->userRelated([
ActiveQueryContent::USER_RELATED_SCOPE_SPACES,
ActiveQueryContent::USER_RELATED_SCOPE_FOLLOWED_SPACES
])->readable()->all();

There are the following user related scopes available:

_USER_RELATED_SCOPEOWN: Content created by the given user itself (content.created_by)

_USER_RELATED_SCOPESPACES: Content related to the users member spaces

_USER_RELATED_SCOPE_FOLLOWEDSPACES: Content related to the users followed spaces

_USER_RELATED_SCOPE_FOLLOWEDUSERS: Content related to the users followed user profiles

_USER_RELATED_SCOPE_OWNPROFILE: Content related to the users own profile

In case your content should be movable to other spaces you'll have to enable the ContentActiveRecord::canMove flag.
For complex content-types you may want to overwrite the ContentActiveRecord::afterMove() function.
This is required for example if your content is related to other sub content entries.

By default the url returned by Content::getUrl() links to the space or profile stream with active contentId filter.
If you want to change this behaviour and for example rather link to a content-type specific detail view of your content, you can
implement a ContentActiveRecord::getUrl() method.

The default space stream supports the pinning of content, which will load the pinned entries at the top of the
stream. Normally you won't need to call the pin/unpin methods by yourself, since this is part of the default stream
entry logic. In case your content is not part of the default stream, you may use these functions for your own module logic.

When working with Content or other ContentContainer related data, your controller should extend the
ContentContainerController class.
This controller will automatically search and instantiate a container instance related to the
cguid request parameter and provide additional features as:

Additional access checks

Default layout selection based on container type (User or Space)

Create container URL's for the given container

By default a ContentContainerController will block requests without a given cguid request parameter.
If you need to implement a controller which should be able to handle container related as well as global
requests you'll have to set the ContentContainerController::requireContainer field to false.

In your controller logic you can access the related cotnainer by means of $this->contentContainer.

You can even restrict the allowed container types by setting the ContentContainerController::validContentContainerClasses array.
This can be useful if your controller should only handle space or user related requests.

Urls pointing to a container action should be created by using the ContentContainerActiveRecord::createUrl() function.
This will add the required cguid parameter to your request.

// Direct ContentContainer call$space->createUrl('/module/controller/action');
// Or by means of a ContentActiveRecord$model->content->createUrl('/module/controller/action');
// Within a ContentContainerController:$this->contentContainer->createUrl('/module/controller/action');