Merge branch 'v1.3-dev' of https://github.com/humhub/humhub into v1.3-dev

# Conflicts:
#	protected/humhub/config/common.php
#	protected/humhub/docs/CHANGELOG_DEV.md
#	protected/humhub/docs/guide/bundled-software.md
#	protected/humhub/modules/content/widgets/richtext/HumHubRichText.php
#	themes/HumHub/css/theme.css
This commit is contained in:
buddh4 2018-02-08 14:35:13 +01:00
commit 975e715995
3184 changed files with 46761 additions and 42325 deletions

View File

@ -7,7 +7,7 @@ engines:
phpcodesniffer:
enabled: true
config:
standard: "PSR1,PSR2"
standard: "ruleset.xml"
ratings:
paths:
@ -15,3 +15,5 @@ ratings:
exclude_paths:
- "**/messages/"
- "**/codeception/_support/_generated/"
- "static/assets/"

View File

@ -4,13 +4,17 @@ RewriteEngine on
# uncomment to force https requests
#RewriteCond %{HTTPS} !=on
#RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/.*$ [NC]
#RewriteCond %{REQUEST_URI} !^/\.well-known/acme-challenge/[0-9a-zA-Z_-]+$ [NC]
#RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# prevent httpd from serving dotfiles (.htaccess, .svn, .git, etc.) - except let's encrypt challenge
RedirectMatch 403 ^/?\.(?!/well-known/acme-challenge/[\w-]{43}$)
# ensure permalink when url rewriting was enabled (index.php?r=content/perma&id=6 => /content/perma/?id=6
RewriteCond %{QUERY_STRING} ^r=content(/|%2)perma&id=([0-9]*)$
RewriteRule ^index\.php$ %{REQUEST_URI}/content/perma/?id=%2 [R=302,L]
RewriteCond %{REQUEST_URI}::$1 ^(/.+)/(.*)::\2$
RewriteRule ^(.*) - [E=BASE:%1]

View File

@ -75,6 +75,7 @@
"platform": {
"php": "5.6"
},
"process-timeout": 1800,
"vendor-dir": "protected/vendor"
},
"scripts": {

View File

@ -26,6 +26,6 @@ class JqueryWidgetAsset extends AssetBundle
/**
* @inheritdoc
*/
public $js = ['ui/minified/widget.min.js'];
public $js = ['ui/minified/widget.js'];
}

View File

@ -9,7 +9,6 @@
namespace humhub\components;
use Yii;
use yii\base\Event;
use humhub\libs\WidgetCreateEvent;
/**
@ -46,7 +45,7 @@ class Widget extends \yii\base\Widget
return;
}
Event::trigger(self::className(), self::EVENT_CREATE, new WidgetCreateEvent($config));
\yii\base\Event::trigger(self::className(), self::EVENT_CREATE, new WidgetCreateEvent($config));
ob_start();
ob_implicit_flush(false);

View File

@ -1,21 +1,13 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2017 HumHub GmbH & Co. KG
* @copyright Copyright (c) 2018 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*
*/
/**
* Created by PhpStorm.
* User: buddha
* Date: 30.07.2017
* Time: 03:07
*/
namespace humhub\components\access;
use Yii;
use yii\base\InvalidParamException;
use yii\base\Object;
@ -80,11 +72,11 @@ abstract class AccessValidator extends Object
public function init()
{
if(!$this->name) {
if (!$this->name) {
$this->name = static::class;
}
if(empty($this->reason)) {
if (empty($this->reason)) {
$this->reason = Yii::t('error', 'You are not permitted to access this section.');
}
}
@ -97,7 +89,7 @@ abstract class AccessValidator extends Object
*
* @return boolean true if validation passed otherwise true
*/
abstract function run();
abstract public function run();
/**
* Filters out all rules which are not related to this validator.
@ -107,7 +99,7 @@ abstract class AccessValidator extends Object
*/
protected function filterRelatedRules($rules = null)
{
if($rules === null) {
if ($rules === null) {
$rules = $this->access->getRules();
}
@ -115,11 +107,11 @@ abstract class AccessValidator extends Object
foreach ($rules as $rule) {
$ruleName = $this->getRuleName($rule);
if($this->name === $ruleName) {
if ($this->name === $ruleName) {
$result[] = $rule;
}
}
return $result;
}
@ -185,12 +177,12 @@ abstract class AccessValidator extends Object
*/
protected function getRuleName($rule)
{
if(empty($rule)) {
if (empty($rule)) {
return null;
}
$firstKey = current(array_keys($rule));
if(is_string($firstKey)) {
if (is_string($firstKey)) {
return $firstKey;
} else {
return $rule[$firstKey];
@ -212,4 +204,4 @@ abstract class AccessValidator extends Object
{
return $this->code;
}
}
}

View File

@ -6,16 +6,8 @@
*
*/
/**
* Created by PhpStorm.
* User: buddha
* Date: 28.07.2017
* Time: 17:43
*/
namespace humhub\components\access;
/**
* This Validator filters out non action related rules and supports a $strict mode, which will require all validator
* related rules to pass.
@ -43,25 +35,25 @@ abstract class ActionAccessValidator extends AccessValidator
* @param $access ControllerAccess
* @return boolean
*/
public function run()
{
$rules = $this->filterRelatedRules();
public function run()
{
$rules = $this->filterRelatedRules();
if(empty($rules)) {
return true;
}
if(empty($rules)) {
return true;
}
foreach ($rules as $rule) {
$can = $this->validate($rule);
if ($can && !$this->strict) {
return true;
} else if (!$can && $this->strict) {
return false;
}
}
foreach ($rules as $rule) {
$can = $this->validate($rule);
if ($can && !$this->strict) {
return true;
} elseif (!$can && $this->strict) {
return false;
}
}
return $this->strict;
}
return $this->strict;
}
/**
* Filters out rules not related to the current validator and action.
@ -73,12 +65,13 @@ abstract class ActionAccessValidator extends AccessValidator
{
$result = [];
foreach (parent::filterRelatedRules($rules) as $rule) {
if($this->isActionRelated($rule)) {
if ($this->isActionRelated($rule)) {
$result[] = $rule;
}
}
return $result;
}
protected abstract function validate($rule);
}
abstract protected function validate($rule);
}

View File

@ -6,13 +6,6 @@
*
*/
/**
* Created by PhpStorm.
* User: buddha
* Date: 26.07.2017
* Time: 13:33
*/
namespace humhub\components\access;
use humhub\libs\BasePermission;
@ -30,7 +23,8 @@ use yii\web\Controller;
*
* The actual permission rule verification is handled by the [[run()]] function.
*
* Subclasses can extend the set of available validators by calling [[registerValidator()]] and providing a validator setting array as:
* Subclasses can extend the set of available validators by calling [[registerValidator()]]
* and providing a validator setting array as:
*
* ```php
* public function init()
@ -44,8 +38,8 @@ use yii\web\Controller;
* }
* ```
*
* The previous example registered a new validator responsible for validating rules with the name `validateMyRule` and validation
* handler function `validateMyRule` which defines an handler method within the subclass.
* The previous example registered a new validator responsible for validating rules with the name `validateMyRule`
* and validation handler function `validateMyRule` which defines an handler method within the subclass.
*
* Custom Validators can also be added by means of a Validator class as in the following example:
*
@ -70,7 +64,8 @@ use yii\web\Controller;
*
* If no action array is provided, the rule is considered to be controller global and will be verified for all actions.
*
* If a rule for a given name could not be found, the ControllerAccess tries to determine a custom rule validator set by the controller itself:
* If a rule for a given name could not be found, the ControllerAccess tries to determine a custom rule validator
* set by the controller itself:
*
* ```php
* ['validateMyCustomRule', 'someParameter' => $value]
@ -91,8 +86,8 @@ use yii\web\Controller;
* }
* ```
*
* By defining the [[fixedRules]] array property a ControllerAccess can define rules which are always applied, this property (or [[getFixedRules()]] function
* may be overwritten by subclasses.
* By defining the [[fixedRules]] array property a ControllerAccess can define rules which are always applied,
* this property (or [[getFixedRules()]] function may be overwritten by subclasses.
*
* The following rules are available by default:
*
@ -116,7 +111,8 @@ class ControllerAccess extends Object
const ACTION_SETTING_TYPE_OPTION_ONLY = 0;
/**
* Allows the action rule setting by extra option ['myRule', 'actions' => ['action1', 'action2']] or immediate ['myRule' => ['action1', 'action2']]
* Allows the action rule setting by extra option ['myRule', 'actions' => ['action1', 'action2']]
* or immediate ['myRule' => ['action1', 'action2']]
*/
const ACTION_SETTING_TYPE_BOTH = 1;
@ -126,7 +122,8 @@ class ControllerAccess extends Object
const RULE_ADMIN_ONLY = 'admin';
/**
* Validate against a given set of permissions e.g.: ['permission' => [MyPermission::class], 'actions' => ['action1']]
* Validate against a given set of permissions e.g.:
* ['permission' => [MyPermission::class], 'actions' => ['action1']]
*/
const RULE_PERMISSION = 'permission';
@ -214,17 +211,40 @@ class ControllerAccess extends Object
$this->action = Yii::$app->controller->action->id;
}
$this->registerValidator([self::RULE_STRICT => 'validateStrictMode', 'reason' => Yii::t('error', 'Guest mode not active, please login first.'), 'code' => 401]);
$this->registerValidator([self::RULE_UNAPPROVED_USER => 'validateUnapprovedUser', 'reason' => Yii::t('error', 'Your user account has not been approved yet, please try again later or contact a network administrator.'), 'code' => 401]);
$this->registerValidator([self::RULE_DISABLED_USER => 'validateDisabledUser', 'reason' => Yii::t('error', 'Your user account is inactive, please login with an active account or contact a network administrator.'), 'code' => 401]);
$this->registerValidator([self::RULE_LOGGED_IN_ONLY => 'validateLoggedInOnly', 'reason' => Yii::t('error', 'Login required for this section.'), 'code' => 401]);
$this->registerValidator([
self::RULE_STRICT => 'validateStrictMode',
'reason' => Yii::t('error', 'Guest mode not active, please login first.'),
'code' => 401
]);
$this->registerValidator([
self::RULE_UNAPPROVED_USER => 'validateUnapprovedUser',
'reason' => Yii::t('error', 'Your user account has not been approved yet, please try again later or contact a network administrator.'),
'code' => 401
]);
$this->registerValidator([
self::RULE_DISABLED_USER => 'validateDisabledUser',
'reason' => Yii::t('error', 'Your user account is inactive, please login with an active account or contact a network administrator.'),
'code' => 401
]);
$this->registerValidator([
self::RULE_LOGGED_IN_ONLY => 'validateLoggedInOnly',
'reason' => Yii::t('error', 'Login required for this section.'),
'code' => 401
]);
// We don't set code 401 since we want to show an error instead of redirecting to login
$this->registerValidator(GuestAccessValidator::class);
$this->registerValidator([self::RULE_ADMIN_ONLY => 'validateAdminOnly', 'reason' => Yii::t('error', 'You need admin permissions to access this section.')]);
$this->registerValidator([
self::RULE_ADMIN_ONLY => 'validateAdminOnly',
'reason' => Yii::t('error', 'You need admin permissions to access this section.')
]);
$this->registerValidator(PermissionAccessValidator::class);
$this->registerValidator(DeprecatedPermissionAccessValidator::class);
$this->registerValidator([self::RULE_POST => 'validatePostRequest', 'code' => 405, 'reason' => Yii::t('base', 'Invalid request method!')]);
$this->registerValidator([
self::RULE_POST => 'validatePostRequest',
'reason' => Yii::t('base', 'Invalid request method!'),
'code' => 405
]);
$this->registerValidator([self::RULE_JSON => 'validateJsonResponse']);
}
@ -260,7 +280,7 @@ class ControllerAccess extends Object
*/
protected function registerValidator($options)
{
if(is_string($options)) {
if (is_string($options)) {
$options = ['class' => $options];
}
@ -268,9 +288,9 @@ class ControllerAccess extends Object
$name = $this->getName($options);
if($name == 'class') {
if ($name == 'class') {
$validator = Yii::createObject($options);
} else if(class_exists($name)) {
} elseif (class_exists($name)) {
unset($options[0]);
$options['class'] = $name;
$validator = Yii::createObject($options);
@ -294,11 +314,12 @@ class ControllerAccess extends Object
{
$finished = [];
foreach($this->rules as $rule) {
foreach ($this->rules as $rule) {
$ruleName = $this->getName($rule);
// A validator validates all rules of the given $name, so we don't have to rerun the validation here if already handled
if(in_array($ruleName, $finished)) {
// A validator validates all rules of the given $name,
// so we don't have to rerun the validation here if already handled
if (in_array($ruleName, $finished)) {
continue;
}
@ -306,7 +327,7 @@ class ControllerAccess extends Object
$validator = $this->findValidator($ruleName);
if(!$validator->run()) {
if (!$validator->run()) {
$this->reason = (!$this->reason) ? $validator->getReason() : $this->reason;
$this->code = (!$this->code) ? $validator->getCode(): $this->code;
return false;
@ -318,7 +339,7 @@ class ControllerAccess extends Object
protected function findValidator($ruleName)
{
if(isset($this->validators[$ruleName])) {
if (isset($this->validators[$ruleName])) {
return $this->validators[$ruleName];
}
@ -327,7 +348,7 @@ class ControllerAccess extends Object
protected function getCustomValidator($ruleName)
{
if($this->owner && method_exists($this->owner, $ruleName)) {
if ($this->owner && method_exists($this->owner, $ruleName)) {
return new DelegateAccessValidator([
'access' => $this,
'owner' => $this->owner,
@ -354,12 +375,12 @@ class ControllerAccess extends Object
*/
protected function getName($arr)
{
if(empty($arr)) {
if (empty($arr)) {
return null;
}
$firstKey = current(array_keys($arr));
if(is_string($firstKey)) {
if (is_string($firstKey)) {
return $firstKey;
} else {
return $arr[$firstKey];
@ -412,6 +433,7 @@ class ControllerAccess extends Object
public function validateJsonResponse()
{
Yii::$app->response->format = 'json';
return true;
}
@ -443,4 +465,4 @@ class ControllerAccess extends Object
{
return !$this->isGuest() && $this->user->isSystemAdmin();
}
}
}

View File

@ -1,21 +1,13 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2017 HumHub GmbH & Co. KG
* @copyright Copyright (c) 2018 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*
*/
/**
* Created by PhpStorm.
* User: buddha
* Date: 30.07.2017
* Time: 04:04
*/
namespace humhub\components\access;
use Yii;
use yii\base\InvalidParamException;
@ -27,7 +19,7 @@ class PermissionAccessValidator extends ActionAccessValidator
protected function validate($rule)
{
if(Yii::$app->user->isAdmin()) {
if (Yii::$app->user->isAdmin()) {
return true;
}
@ -61,4 +53,4 @@ class PermissionAccessValidator extends ActionAccessValidator
return $actions;
}
}
}

View File

@ -2,22 +2,23 @@
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2017 HumHub GmbH & Co. KG
* @copyright Copyright (c) 2018 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\components\behaviors;
use Yii;
use yii\web\ForbiddenHttpException;
use humhub\components\access\ControllerAccess;
use Yii;
use yii\base\ActionFilter;
use yii\web\ForbiddenHttpException;
use yii\web\HttpException;
/**
* Handles the AccessControl for a Controller.
*
* Controller level AccessRules can be provided by either setting the [[rules]] array, or by implementing a `getAccessRules()` function
* within the controller itself (prefered).
* Controller level AccessRules can be provided by either setting the [[rules]] array,
* or by implementing a `getAccessRules()` function within the controller itself (prefered).
*
* **Examples:**
*
@ -78,20 +79,21 @@ use yii\web\HttpException;
*
* ```
*
* The list of available rules is given by the [[\humhub\components\access\ControllerAccess]] class set by a controller. By
* default the base [[\humhub\components\access\ControllerAccess]] class will be used.
* The list of available rules is given by the [[\humhub\components\access\ControllerAccess]] class set by a controller.
* By default the base [[\humhub\components\access\ControllerAccess]] class will be used.
*
* The default ControllerAccess class can be overwritten by implementing the `getAccess()` function within a controller, which should return an instance
* of ControllerAccess.
* The default ControllerAccess class can be overwritten by implementing the `getAccess()` function within a controller,
* which should return an instance of ControllerAccess.
*
* > Note: You can also use the [[\humhub\components\Controller::access]] property to define a ControllerAccess class string.
* > Note: You can also use the [[\humhub\components\Controller::access]] property
* to define a ControllerAccess class string.
*
*
*
* @see ControllerAccess
* @author luke
*/
class AccessControl extends \yii\base\ActionFilter
class AccessControl extends ActionFilter
{
/**
@ -126,7 +128,7 @@ class AccessControl extends \yii\base\ActionFilter
/**
* @var ControllerAccess instance
*/
protected $_controllerAccess;
protected $controllerAccess;
/**
* @inheritdoc
@ -134,15 +136,17 @@ class AccessControl extends \yii\base\ActionFilter
public function beforeAction($action)
{
// Bypass when not installed for installer
if (empty(Yii::$app->params['installed']) && Yii::$app->controller->module != null && Yii::$app->controller->module->id == 'installer') {
return true;
if (empty(Yii::$app->params['installed']) &&
Yii::$app->controller->module != null &&
Yii::$app->controller->module->id == 'installer') {
return true;
}
$this->handleDeprecatedSettings();
$this->_controllerAccess = $this->getControllerAccess($this->rules);
$this->controllerAccess = $this->getControllerAccess($this->rules);
if(!$this->_controllerAccess->run()) {
if($this->_controllerAccess->code == 401) {
if (!$this->controllerAccess->run()) {
if ($this->controllerAccess->code == 401) {
return $this->loginRequired();
} else {
$this->forbidden();
@ -157,15 +161,15 @@ class AccessControl extends \yii\base\ActionFilter
*/
protected function handleDeprecatedSettings()
{
if($this->adminOnly) {
if ($this->adminOnly) {
$this->rules[] = [ControllerAccess::RULE_ADMIN_ONLY];
}
if($this->loggedInOnly) {
if ($this->loggedInOnly) {
$this->rules[] = [ControllerAccess::RULE_LOGGED_IN_ONLY];
}
if(!empty($this->guestAllowedActions)) {
if (!empty($this->guestAllowedActions)) {
$this->rules[] = ['guestAccess' => $this->guestAllowedActions];
}
}
@ -178,16 +182,16 @@ class AccessControl extends \yii\base\ActionFilter
*/
protected function getControllerAccess($rules = null)
{
if($rules === null) {
if ($rules === null) {
$rules = [['strict']];
}
$instance = null;
if(method_exists($this->owner, 'getAccess')) {
if (method_exists($this->owner, 'getAccess')) {
$instance = $this->owner->getAccess();
}
if(!$instance) {
if (!$instance) {
// fixes legacy behavior settings compatibility issue with no rules given
$instance = new ControllerAccess();
}
@ -198,13 +202,12 @@ class AccessControl extends \yii\base\ActionFilter
return $instance;
}
/**
* @throws ForbiddenHttpException
*/
protected function forbidden()
{
throw new HttpException($this->_controllerAccess->code, $this->_controllerAccess->reason);
throw new HttpException($this->controllerAccess->code, $this->controllerAccess->reason);
}
/**
@ -214,6 +217,7 @@ class AccessControl extends \yii\base\ActionFilter
{
Yii::$app->user->logout();
Yii::$app->user->loginRequired();
return false;
}
}

View File

@ -2,7 +2,7 @@
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2017 HumHub GmbH & Co. KG
* @copyright Copyright (c) 2018 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
@ -28,7 +28,7 @@ abstract class AbstractDateValidator extends Validator
$date = $model->$attribute;
if (is_string($model->$attribute)) {
$date = strtotime($model->$attribute);
} else if ($model->$attribute instanceof DateTime) {
} elseif ($model->$attribute instanceof DateTime) {
$date = $model->$attribute->getTimestamp();
}

View File

@ -2,7 +2,7 @@
/**
* This file is generated by the "yii asset" command.
* DO NOT MODIFY THIS FILE DIRECTLY.
* @version 2017-10-23 13:26:02
* @version 2017-12-13 17:23:23
*/
return [
'all' => [
@ -10,10 +10,10 @@ return [
'basePath' => '@webroot-static',
'baseUrl' => '@web-static',
'js' => [
'js/all-e6da5fb463384914aac09ab5bc1121bb.js',
'js/all-80cc587bf42b9f4207d602b7bba9bd46.js',
],
'css' => [
'css/all-59bdfa4c0b50304180be32b3f5b0d157.css',
'css/all-2febca3798ebc2dcc727616c385acb02.css',
],
'sourcePath' => null,
'depends' => [],

View File

@ -1,6 +1,48 @@
HumHub Change Log
=================
1.2.5 (Not released)
---------------------
- Enh: Added BaseURL setting protocol scheme validation
- Fix #2849: ActiveQueryContent doesn't find public profile content when guest access is enabled
- Enh: Fixed username alignment in comments (@githubjeka)
- Enh: More readable WallEntryAddon links (@githubjeka)
- Fix: Documentation grammar fixes (@Felli)
- Fix: Let's Encrypt ACME Error (@Felli)
- Fix: Typo in password recovery (@acs-ferreira)
- Fix: Profile posts of friends not appears on dashboard
- Fix #2745: Yii2 2.0.13 will break the admin interface
- Enh: Allow auto detection of response dataType
- Fix #2947: Allow json success result on modalSubmit
- Enh: Disabled automatic content following on likes by default
- Enh: Improved IntegrityChecker memory usage
1.2.4 (December 13, 2017)
--------------------------
- Enh: Translation updates
- Fix: Added `ManageSpaces` and SystemAdmin check to `UserGroupAccessValidator`.
- Fix: Only include content with `stream_channel = default` into spacechooser update count.
- Enh: Add LinkedIn auth to login. (Felli)
- Enh: Add Twitter auth to login. (Felli)
- Enh: Add Instagram auth to login. (Felli)
- Enh: Add Twitter, LinkedIn & Instagram auth to docs (Felli)
- Enh: Make lucene search term limit configurable via `ZendLuceneSearch::$searchItemLimit`.
- Fix: Empty stream message between friends
- Enh: Improve composer-asset-plugin config (cebe)
- Enh: Added a link to the permalink from the ago text (benklop)
- Enh: Added directory group description (githubjeka)
- Enh: Added configuration option to include user profile posts in dashboard without following
- Fix: User profile sidebar disappered
- Fix: Like notification for comments not working
- Fix: Add example users to default Users group
- Fix #2851: getting model attribute value using Html::getAttributeValue()
- Fix #2844: Directory member search broken on page 2
- Fix #2702: Disable content search for guest users due to space visibility
- Fix #2806: Register process broken on some environments (Felli)
1.2.3 (October 23, 2017)
-------------------------

View File

@ -34,3 +34,8 @@ HumHub Change Log - v1.3-dev Branch
- Enh: Added `humhub.user.getLocale()` javascript helper for checking the user locale on client side
- Enh: Added `humhub\widgets\InputWidget::getValue()` for determining the field value
- Enh: Added `humhub.client.json` for directly receiving the json result instead of a response wrapper object
- Enh: Added option ContentContainerController to restrict container type
- Enh: Ensure valid permalinks when URL rewriting is enabled
- Fix: Birthday field refactoring (@danielkesselberg)
- Enh #2811: Added option to resend invites (@danielkesselberg)

View File

@ -1,13 +1,13 @@
Welcome
=======
Here you will find helpful information on how to create, maintain, and make the most of an social network built using the HumHub solution.
Here you will find helpful information on how to create, maintain, and make the most of a social network built using the HumHub solution.
All documentations located on docs.humhub.org refers to the latest version of HumHub. If you're using an older version, you can find the related documentation in the
folder /protected/humhub/docs.
All documentation located on docs.humhub.org refers to the latest version of HumHub. If you're using an older version, you can find the related documentation in the folder /protected/humhub/docs.
Documentations
--------------
- [Basics](basics/README.md) (Note: This directory stores basic knowledge on HumHub Features)
- [Installation and Administration](admin/README.md)
- [Theming](theme/README.md)
- [Core and Module Development](developer/README.md)

View File

@ -22,9 +22,6 @@ Administration Topics
* [Backup HumHub](backup.md)
* [Performance Tuning](performance.md)
* [Custom Configurations](advanced-configuration.md)
* [Redis Integration](redis.md)
* [Asynchronous Task Processing](asynchronous-tasks.md)
* [Push Updates](push-updates.md)
* [Authentication and LDAP](authentication.md)
* [Search System](search.md)
* [Translations](translations.md)

View File

@ -6,10 +6,10 @@ You can overwrite the default HumHub / Yii configuration in the folder `/protect
File Overview
-------------
- **common.php** - Configuration used for the Console and the Web Application
- **web.php** - Configuration used for the Web Application only
- **console.log** - Configuration used for the Console Application only
- **dynamic.php** - Dynamically generated configuration - do not edit manually!
- **common.php** - Configuration used in Console & Web Application
- **web.php** - Configuration used in Web Application only
- **console.log** - Configuration used in Console Application only
- **dynamic.php** - Dynamic generated configuration - do not edit manually!
@ -37,10 +37,7 @@ Configuration file loading order
# Application Params
Some application behaviour can be configured by changing the application parameters within your `common.php`, `web.php` or `console.php`:
The following configuration block will disable pjax support on your site for example:
Some application behaviours can be configured, by changing application parameters within your `common.php`, `web.php` or `console.php`:
```
return [
@ -50,18 +47,40 @@ return [
];
```
Thre previous configuration will disable pjax support on your site.
Available params:
- `allowedLanguages` see the [Translations Section](translations.md)
- `defaultPermissions` see [Permissions Section (TBD)]()
- `enablePjax` used to disable/enable pjax support (default true)
## Overwrite default Permissions
Default permission can be overwritten within `humhub/config/common.php` by means of the `defaultPermissions` params array.
The following example overwrites the default permission of `humhub\modules\mymodule\permissions\MyPermission` for the
given groups.
```
return [
'params' => [
'defaultPermissions' => [
'humhub\modules\mymodule\permissions\MyPermission' => [
\humhub\modules\user\models\User::USERGROUP_SELF => \humhub\libs\BasePermission::STATE_ALLOW,
\humhub\modules\user\models\User::USERGROUP_USER => \humhub\libs\BasePermission::STATE_ALLOW,
\humhub\modules\user\models\User::USERGROUP_FRIEND => \humhub\libs\BasePermission::STATE_ALLOW,
\humhub\modules\user\models\User::USERGROUP_GUEST => \humhub\libs\BasePermission::STATE_ALLOW,
],
]
]
]
```
# Statistics/Tracking
Your tracking code can be managed under `Administration -> Settings -> Advanced -> Statistics`.
In order to send the tracking code in case that both, the pjax as well as the full page loads, you have to add the following to your statistics code (refers to Google Analytics):
In order to send the tracking code in case of pjax page loads as well as full page loads, you have to add the following to your statistics code by the example of google analytics:
```javascript

View File

@ -1,14 +1,11 @@
Authentication
==============
LDAP
----
You can enable authentication against LDAP (e.g. against Active Directory or OpenLDAP) at: `Administration -> Users -> Settings-> LDAP`.
The profile field attribute mapping can be defined at `Administration -> Users -> Profile -> Select profile field -> LDAP Attribute`.
### Date field synchronisation
If you're using custom date formats in our ldap backend, you can specify different formats
in the [configuration file](advanced-configuration.md).
@ -24,11 +21,8 @@ in the [configuration file](advanced-configuration.md).
Note: Make sure to use lower case in the field.
Facebook
--------
In order to use Facebook OAuth you must register your application at <https://developers.facebook.com/apps>.
Add the following block to your configuration (protected/config/common.php):
@ -54,18 +48,49 @@ return [
];
```
Twitter
------
In order to use Twitter OAuth you must register your application at <https://apps.twitter.com/>.
Add the following block to your configuration (protected/config/common.php):
```php
return [
// ...
'components' => [
// ...
'authClientCollection' => [
'clients' => [
// ...
'twitter' => [
'class' => 'yii\authclient\clients\Twitter',
'attributeParams' => [
'include_email' => 'true'
],
'consumerKey' => 'Your Twitter Consumer key here',
'consumerSecret' => 'Your Twitter Consumer secret here',
],
],
],
// ...
],
// ...
];
```
Google
------
In order to use Google OAuth you must create a **project** at <https://console.developers.google.com/project>
and setup its credentials at <https://console.developers.google.com/project/[yourProjectId]/apiui/credential>.
and set up its credentials at <https://console.developers.google.com/project/[yourProjectId]/apiui/credential>.
In order to enable using scopes for retrieving user attributes, you have to enable Google+ API at
In order to enable using scopes for retrieving user attributes, you should also enable Google+ API at
<https://console.developers.google.com/project/[yourProjectId]/apiui/api/plus>.
Authorization callback URLs:
Add one of the following **authorization callback URLs** to your googles **Credentials** configuration:
- http://<domain>/<path-to-humhub>/user/auth/external?authclient=google (With clean urls enabled)
- http://<domain>/<path-to-humhub>/index.php?r=user%2Fauth%2Fexternal&authclient=google (Without clean urls)
- http://domain/path-to-humhub/user/auth/external?authclient=google (With clean urls enabled)
- http://domain/path-to-humhub/index.php?r=user%2Fauth%2Fexternal&authclient=google (Without clean urls)
>Note: Replace **domain** and **path-to-humhub** in the mentioned redirect urls.
@ -94,14 +119,13 @@ return [
GitHub
------
In order to use GitHub OAuth you must register your application at <https://github.com/settings/applications/new>.
Authorization callback URLs:
- http://domain/path-to-humhub/user/auth/external (With clean urls enabled)
- http://domain/path-to-humhub/index.php?r=user%2Fauth%2Fexternal (Without clean urls)
Add following block to your configuration (protected/config/common.php):
Add the following block to your configuration (protected/config/common.php):
```php
return [
@ -127,18 +151,16 @@ return [
];
```
Microsoft Live
--------------
In order to use Microsoft Live OAuth you must register your application at <https://account.live.com/developers/applications>.
Also add a new Platform and allow following Redirect URI.
Also, add a new Platform and allow following Redirect URI.
- https://domain/path-to-humhub/user/auth/external (With clean urls enabled)
- https://domain/path-to-humhub/index.php (Without clean urls)
Add following block to your configuration (protected/config/common.php):
Add the following block to your configuration (protected/config/common.php):
```php
return [
@ -161,8 +183,34 @@ return [
];
```
LinkedIn
------
In order to use LinkedIn OAuth you must register your application at <https://www.linkedin.com/developer/apps/>.
Add the following block to your configuration (protected/config/common.php):
```php
return [
// ...
'components' => [
// ...
'authClientCollection' => [
'clients' => [
// ...
'linkedin' => [
'class' => 'humhub\modules\user\authclient\LinkedIn',
'clientId' => 'Your LinkedIn Client ID here',
'clientSecret' => 'Your LinkedIn Client Secret here',
],
],
],
// ...
],
// ...
];
```
Other providers
---------------
Please see [Development - Authentication](dev-authentication.md) for more information
about additional authentication providers.

View File

@ -1,5 +1,12 @@
Console
=======
TBD
Some administrative tasks can also or exclusively be executed by console. All available console commands can be displayed
by executing the following command within the `protected` directory of your humhub installation.
```
php yii
```
![Command Overview](images/commandOverview.png)

View File

@ -0,0 +1,71 @@
Cron Job Setup
=======
The following guides are meant to help you with your Cron Job setup, since those settings are highly dependent on your actual environment we can't assure those setting will work for your.
> Note: Make sure to use the right [php cli executable](http://php.net/manual/en/features.commandline.introduction.php) for your jobs!
### CloudLinux (CentOS) 6
The following is a default setup for CloudLinux (CentOS) 6 and may not work for all users.
```
/usr/local/bin/php /home/USERNAME/public_html/WEB-DIRECTORY/protected/yii cron/hourly >/dev/null 2>&1
30 * * * *
/usr/local/bin/php /home/USERNAME/public_html/WEB-DIRECTORY/protected/yii cron/daily >/dev/null 2>&1
00 18 * * *
```
### cPanel Hosted Server
The following is a default setup for cPanel Hosted Server and may not work for all users.
```
/usr/local/bin/php /home/USERNAME/public_html/WEB-DIRECTORY/protected/yii cron/hourly >/dev/null 2>&1
0,30 * * * *
/usr/local/bin/php /home/USERNAME/public_html/WEB-DIRECTORY/protected/yii cron/daily >/dev/null 2>&1
00 0,12 * * *
```
### IIS Windows Server
Using [Schtasks](https://technet.microsoft.com/en-us/library/cc725744.aspx) would be recommended over many other options for Windows 2012 and Windows 8 users.
`Example TBA`
### Plesk
Refer to this [post](https://stackoverflow.com/questions/16700749/setting-up-cron-task-in-plesk-11)
![](http://i.imgur.com/TbWEsjC.png)
### OVH
[Follow this link](https://www.ovh.com/us/g1990.hosting_automated_taskscron)!
Create the following files then follow the above link.
**cronh.php**
`<?php $humhubh = '/usr/local/php5.6/bin/php '.__DIR__.'/protected/yii cron/hourly '; exec($humhubh); ?>`
**crond.php**
`<?php $humhubd = '/usr/local/php5.6/bin/php '.__DIR__.'/protected/yii cron/daily '; exec($humhubd); ?>`
### Debian
Please read up on this [article](https://debian-administration.org/article/56/Command_scheduling_with_cron).
`Example TBA`
### Ubuntu
Please read up on this [how-to guide](https://help.ubuntu.com/community/CronHowto).
`Example TBA`
### Other Server(s)
`TBA`
### *IMPORTANT NOTICE*
*This guide is subject to changes and all information provided are for example use, it is best to speak with your service providers about how best to setup your Cron Jobs with their services.*

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

View File

@ -3,23 +3,6 @@ Configuration
> NOTE: Before going to production, see also the [Security Chapter](security.md)
Basic Settings
-------
Once installed, you should have a look at the basic application settings under `Administration/Settings/Basic`
for settings as:
- Base Url
- Default language
- Time zone
- etc.
Within this view you can also select **default spaces**, which will be automatically assigned to new members.
Advanced Settings
-------
You may also check the advanced settings under `Administration/Settings/Advanced` and Notification settings to set
some default values for your user.
E-Mails
-------
@ -27,7 +10,8 @@ E-Mails
Depending on your environment you are using, you may want to specify a local or remote SMTP Server.
You can change the mail-server settings under `Administration -> Mailing -> Server Settings`.
By default the PHP Mail Transport is used. <http://php.net/manual/en/mail.setup.php>
By default, the PHP Mail Transport is used. <http://php.net/manual/en/mail.setup.php>
CronJobs
@ -42,7 +26,7 @@ Example Tab:
30 * * * * /path/to/humhub/protected/yii cron/hourly >/dev/null 2>&1
00 18 * * * /path/to/humhub/protected/yii cron/daily >/dev/null 2>&1
```
> Note: For more help refer to [here](cron-jobs.md)!
Url Rewriting (Optional)
------------------------
@ -68,4 +52,4 @@ return [
Job Scheduling
--------------
TBD
TBD

View File

@ -4,28 +4,27 @@ Installation
> Note: It's also possible to install and build HumHub directly from our **Git Repository**.
Please see [Developer Installation](../developer/git-installation.md) for more details.
Database
--------
Create a MySQL Database, e.g.:
```sql
CREATE DATABASE `humhub` CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE DATABASE `humhub` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
GRANT ALL ON `humhub`.* TO `humhub_dbuser`@localhost IDENTIFIED BY 'password_changeme';
FLUSH PRIVILEGES;
```
> Note: Do not forget to change the `humhub_dbuser` and `password_changeme` placeholders!
> Warning: Make sure to use the **utf8_general_ci** database collation!
> Note: `utf8mb4` is prefered over `utf8` since MySQL 5.5.3 please refer to the [mysql documentation](https://dev.mysql.com/doc/refman/5.5/en/charset-unicode-utf8mb4.html) for more infos.
> Warning: Make sure to use the **utf8mb4_unicode_ci** database collation!
Download HumHub Core Files
---------------------------
The easiest way to get HumHub, is the direct download of the complete package under [http://www.humhub.org/downloads](http://www.humhub.org/downloads).
The easiest way to get HumHub, is the direct download of the complete package under [https://www.humhub.org/download](https://www.humhub.org/download).
After the download completed, just extract the package into the htdocs folder of your webserver.

View File

@ -1,11 +1,9 @@
Requirements
============
> Note: All vital requirements will be also checked during the web installer.
Server Requirements
-------------------
* Shell access (e.g. ssh) to server
* PHP 5.6 or later
* MySQL (5.1 or later) or MariaDB with InnoDB storage engine installed
@ -13,27 +11,23 @@ Server Requirements
* A minimum 64 MB of memory allocated to PHP
* A minimum of 50 MB of database space
Required PHP Extensions
-----------------------
* PHP CUrl Extension (w/ SSL Support) <http://de1.php.net/manual/en/curl.setup.php>
* PHP Multibyte String Support <http://php.net/manual/en/mbstring.setup.php>
* PHP PDO MySQL Extension (http://www.php.net/manual/en/ref.pdo-mysql.php)
* PHP Zip Extension (http://php.net/manual/en/book.zip.php)
* PHP EXIF Extension (http://php.net/manual/en/book.exif.php)
* PHP INTL Extension (http://php.net/manual/en/intro.intl.php)
* PHP FileInfo Extension (http://php.net/manual/en/fileinfo.installation.php)
* PHP CUrl Extension (w/ SSL Support) <https://secure.php.net/manual/en/curl.setup.php>
* PHP Multibyte String Support <https://secure.php.net/manual/en/mbstring.setup.php>
* PHP PDO MySQL Extension (https://secure.php.net/manual/en/ref.pdo-mysql.php)
* PHP Zip Extension (https://secure.php.net/manual/en/book.zip.php)
* PHP EXIF Extension (https://secure.php.net/manual/en/book.exif.php)
* PHP INTL Extension (https://secure.php.net/manual/en/intro.intl.php)
* PHP FileInfo Extension (https://secure.php.net/manual/en/fileinfo.installation.php)
Optional PHP Extensions
-----------------------
* ImageMagick
* PHP LDAP Support
* PHP APC
* PHP Memcached
Database
--------
The database user you tell HumHub to connect with must have the following privileges:

View File

@ -18,72 +18,29 @@ cd /path/to/humhub/protected
php yii search/rebuild
```
or by means of [grunt](../developer/core-build.md):
or by means of [grunt](../developer/build.md):
```
grunt build-search
```
File Indexing
-------------
If you like to also index contents of a file (e.g. PDF documents) you need to specify additional parsers.
These parsers are defined in the [configuration file](advanced-configuration.md).
Parsers:
- Apache Tika (https://tika.apache.org/)
- Poppler PDF Utils (https://poppler.freedesktop.org/)
Example:
```php
return [
// ...
'modules' => [
// ...
'file' => [
'converterOptions' => [
'humhub\modules\file\converter\TextConverter' => [
'converter' => [
[
'cmd' => '/usr/bin/pdftotext -q -enc UTF-8 {fileName} {outputFileName}',
'only' => ['pdf']
],
[
'cmd' => '/usr/bin/java -jar /opt/tika-app-1.16.jar --text {fileName} 2>/dev/null',
'except' => ['image/']
]
]
]
]
]
// ...
],
// ...
];
```
Zend Lucence Engine
--------------------
By default HumHub is using a *Lucence* Index (Zend Lucence) to store search data.
By default, HumHub is using a *Lucence* Index (Zend Lucence) to store search data.
Default database folder: `/protected/runtime/searchdb/`
You can modify the default search directory in the [configuration](advanced-configuration.md):
```php
return [
// ...
'params' => [
'search' => [
'zendLucenceDataDir' => '/some/other/path',
return [
// ...
'params' => [
'search' => [
'zendLucenceDataDir' => '/some/other/path',
]
]
]
// ...
];
// ...
];
```

View File

@ -5,7 +5,7 @@ Disable Errors / Debugging
--------------------------
- Modify *index.php* in your humhub root directory
```php
[...]
// comment out the following two lines when deployed to production
@ -16,21 +16,19 @@ Disable Errors / Debugging
- Delete *index-test.php* in your humhub root directory if exists
Protected Directories
---------------------
Make sure following directories are not accessible by web:
Make sure the following directories are not accessible by web:
- protected
- uploads/file
By default these folders are protected with a ".htaccess" file.
Limit User Access
-----------------
If you're running a private social network, make sure the user registration is disabled or the approval system for new users is enabled.
If you're running a private social network, make sure the user registration has been disabled or the approval system for new users has been enabled.
- Disable user registration: `Administration -> Users -> Settings -> Anonymous users can register`
- Enable user approvals: `Administration -> Users -> Settings -> Require group admin approval after registration`
@ -39,9 +37,6 @@ If you're running a private social network, make sure the user registration is d
Keep up with the latest HumHub version
---------------------------------------
As admin you'll receive a notification when a new HumHub version is released. We recommend to always use the latest stable version.
We take security very seriously and continuously improving the security features of HumHub.
As an admin you'll receive a notification when a new HumHub version has been released. We strongly recommend to always use the latest stable version when possible.
We take security very seriously, and we're continuously improving the security features of HumHub.

View File

@ -1,24 +1,24 @@
Spaces
=======
Spaces are one of the main concepts of HumHub for seperating and categorizing content like posts, wikis and polls. A space
Spaces are one of the main concepts of HumHub for separating and categorizing content like posts, wikis and polls. A space
can be described as an independent content container with its own users, permissions and access settings.
A space can be used by space members to share content with other users.
## Add Spaces
Administrators can configure which groups are allowed to create new spaces under **Administration->Groups->Permissions**.
Please read the [Group Section](admin-groups.md) for more information about goups.
Please read the [Group Section](admin-groups.md) for more information about groups.
Spaces can be added by clicking _Add Space_ within the _Space Navigation_.
A new space will require at least a space name. Futhermore you are able to define a space color, a description and advanced access settings.
A new space will require at least a space name. Furthermore, you are able to define a space color, a description and advanced access settings.
The access settings consists of:
- **Join Policy**: Describes who can join the new space.
- **Only by invite**: Only invited users can join the space.
- **Invite and request**: Users can request a space membership beside beeing invited.
- **Only by invitation**: Only invited users can join the space.
- **Invite and request**: Users can request a space membership besides beeing invited.
- **Everyone can enter**: All members can join a space
- **Visibility**: Who can view the space content.
- **Public**: All Users (Registered and Guests users). Available when allow limited access for non-authenticated users (guests) by admin settings.
- **Public**: All Users (Registered and Guests users). Available when allowing limited access for non-authenticated users (guests) by admin settings.
- **Public (registered only)**: All registered users in Humbub (no guests)
- **Private**: This space is invisible for non-space-members
@ -28,7 +28,7 @@ Users can be invited by clicking on the _Invite_ button within the space top men
## Approve New User
New user requests can be viewed, declinded or approved under _Space Settings -> Members -> Pending Approvals_
New user requests can be viewed, declined or approved under _Space Settings -> Members -> Pending Approvals_
## Pending Invites
@ -37,13 +37,13 @@ Pending Invites can be viewed and rejected under _Space Settings -> Members -> P
## Manage Space Members
All members of a Space can be viewed under _Space Settings -> Members_. In this view space administrators are able to remove members
and assign a specfic space group to members.
and assign a specific space group to members.
## Manage Space Permission
Space Permissions can be configured under _Space Settings -> Members -> Permissions.
The permissions can be assigned to specific space groups which can either be assigned
to an user in the _Members_ configuration or are assigned by default (guests/normal user)
to a user in the _Members_ configuration or are assigned by default (guests/normal user)
The available space groups are:
- Owner: The owner of this space (the owner can be assigned by the founder of the group)

View File

@ -19,7 +19,7 @@ Github - Bugtracker
**When filing a new bug, please include:**
- Descriptive title - use keywords so others can find your bug (avoiding duplicates)
- Steps to trigger the problem that are specific, and repeatable
- Specific and repeatable steps that trigger the problem
- What happens when you follow the steps, and what you expected to happen instead.
- Include the exact text of any error messages if applicable (or upload screenshots).
- HumHub version (or if you're pulling directly from Git, your current commit SHA - use git rev-parse HEAD)
@ -28,6 +28,16 @@ Github - Bugtracker
- Modules? Confirm that you've tested with Debug > Reload Without Extensions first (see below).
- Any errors logged in Debug > Show Developer Tools - Console view
Cron Job Setup
----------------------------------------
- Do you have access to setup Cron Jobs?
- Does your server use Cron or Crontab?
- Does your server use a third-party Cron Job provider?
- Are you using VPS or Dedicated/Shared/Other Hosting?
- Can you provide screenshots of your Cron Job settings? (With personal information blurred out!)
- What type of server are you using? (CloudLinux CentOS 6, Windows IIS, or etc)
> Note: For more help refer to [here](cron-jobs.md)!
Direct Support (Enterprise Edition only)
----------------------------------------

View File

@ -1,9 +1,8 @@
Updating to 0.20
================
> NOTE: This guide only affects updates from HumHub 0.11.2 or lower to HumHub 0.20
1. Before you run an update please check, if your installed modules and themes are compatible with your targeted version. If not, you can follow the [Theme Migration Guide](theming-migrate.md) and [Module Migration Guide](dev-migrate.md) to make everything ready for the new version.
1. Before you run an update please check, if your installed modules and themes are compatible with your targeted version. If not, you can follow the [Theme Migration Guide](../theme/migrate.md) and [Module Migration Guide](../developer/migration-guide.md) to make everything ready for the new version.
2. Backup your data:
- Backup the whole HumHub installation folder from your webroot
@ -12,7 +11,7 @@ Updating to 0.20
## Migration Steps
1. Delete your current HumHub installation (Don't forget to make a backup as mentioned above, you will need these files later!)
2. Download the latest HumHub package directly from [http://www.humhub.org/downloads](http://www.humhub.org/downloads) and extract it to your webroot or install it via [GitHub/Composer](admin-installation.md).
2. Download the latest HumHub package directly from [https://www.humhub.org/download](https://www.humhub.org/download) and extract it to your webroot or install it via [GitHub/Composer](../developer/git-installation.md).
3. **IMPORTANT**: Before starting the Web installer you have to restore the /uploads/ directory form your backup to your new installation
4. Start the Web installer (e.g. [http://localhost/humhub](http://localhost/humhub)) and follow the instructions. If you enter the database name from your previous installation, HumHub will automatically migrate your existing database to the new version
5. Reinstall all previously installed modules/themes

View File

@ -3,7 +3,7 @@ Automatic Updating
> Warning: Please check before you run an update, that your installed modules and themes are compatible with the new version. If not, you can follow the migration guides.
- [Theme Migration Guide](../theme/migrate.md)
- [Module Migration Guide](../developer/modules-migrate.md)
- [Module Migration Guide](../developer/migration-guide.md)
> NOTE: Backup your data before updating! See: [Backup Chapter](backup.md)
@ -24,4 +24,4 @@ Updater Module Installation
Troubleshooting
---------------
TBD
TBD

View File

@ -1,18 +1,16 @@
Updating
========
> Warning: Please check before you run an update, that your installed modules and themes are compatible with the new version. If not, you can follow the migration guides.
- [Theme Migration Guide](../theme/migrate.md)
- [Module Migration Guide](../developer/modules-migrate.md)
- [Module Migration Guide](../developer/migration-guide.md)
> NOTE: Only use this guide if you want to update from HumHub 0.20 or higher!
> If you want to update from an older version (e.g. 0.11.2 or lower) to HumHub 0.20+, you have to use this guide: **[Upgrade to 0.20 and above](admin-updating-020.md "Guide: Upgrade to 0.20 and above")**
> If you want to update from an older version (e.g. 0.11.2 or lower) to HumHub 0.20+, you have to use this guide: **[Upgrade to 0.20 and above](updating-020.md "Guide: Upgrade to 0.20 and above")**
> NOTE: Backup your data before updating! See: [Backup Chapter](backup.md)
1. Delete your current HumHub installation (Don't forget to make a backup as mentioned above, you will need these files later!)
2. Download the latest HumHub package from [http://www.humhub.org/downloads](http://www.humhub.org/downloads) and extract the package to your webroot
2. Download the latest HumHub package from [https://www.humhub.org/download](https://www.humhub.org/download) and extract the package to your webroot
3. Restore the following files from backup:
- /uploads/*
- /protected/runtime

View File

@ -0,0 +1,11 @@
# Basics
Core Features
---------------
* [Markdown Cheatsheet](core/md-cheatsheet.md)
* [Emoji Cheatsheet](core/emoji-cheatsheet.md)
Module Features
---------------
`TBA`

View File

@ -0,0 +1,11 @@
# Emoji Cheatsheet
The following is a cheatsheet for the Emoji feature of HumHub
| Emoji Code | Emoji Rendered|
| --- | --- |
| `:smile:` | :smile: |
| `:frown:` | :frown: (Doesn't render on GitHub because it is `frowning`) |
| `:tongue:`| :tongue: |
> Will add more later as it will take some time to finish...

View File

@ -0,0 +1,113 @@
# Markdown Cheatsheet
The following are supported Markdown syntax for the Social Networking Kit [HumHub](https://www.humhub.org)
### Headers
```
# This is an <h1> tag
## This is an <h2> tag
### This is an <h3> tag
#### This is an <h4> tag
##### This is an <h5> tag
###### This is an <h6> tag
```
### Blockquotes
```
As Kanye West said:
> We're living the future so
> the present is our past.
```
### Emphasis
#### Bold
```
**This text will be bold**
__This will also be bold__
```
#### Italic
```
*This text will be italic*
_This will also be italic_
```
> Note: `_You **can** combine both as well_`
### Code
#### Inline Code
```
I think you should use an
`<addr>` element here instead.
```
#### Syntax highlighting
```
\```javascript
function fancyAlert(arg) {
if(arg) {
$.facebox({div:'#foo'})
}
}
```\
```
> Note: That all "`\`" must be removed and all "<code>```</code>" must be on its own line for Syntax highlighting to work!
### Lists
#### Unordered
```
* Item 1
* Item 2
* Item 2a
* Item 2b
```
#### Ordered
```
1. Item 1
2. Item 2
3. Item 3
a. Item 3a
b. Item 3b
```
### Links
```
http://github.com - automatic!
[GitHub](http://github.com)
```
### Images
#### Non-Linked Images
```
![GitHub Logo](/images/logo.png)
Format: ![Alt Text](image url) - Note: Must have a image file type or won't work.
```
#### Linked Images
```
[![Alt Text](/images/logo.png)](www.example.com) - Note: Must have a image file type or won't work.
```
### Tables
```
First Header | Second Header
------------ | -------------
Content from cell 1 | Content from cell 2
Content in the first column | Content in the second column
```
### Strikethrough
```
~~this~~
```
### Ignoring Markdown formatting
```
Let's rename \*our-new-project\* to \*our-old-project\*.
```

View File

@ -4,43 +4,54 @@ Developement Guide
Getting Started
---------------
* [Overview](overview.md)
* [Git Installation](git-installation.md)
* [Development Environment](environment.md)
* [Git/Composer Installation](git-installation.md)
* [Coding Standards](coding-standards.md)
* [Development Environment](environment.md)
* [Migration Guide](migration-guide.md)
Module Development
Modules
---------------
* [Getting Started](modules.md)
* [Asset Management](assets.md)
* [Change core behavior](module-change-behavior.md)
* [Embedded Themes](embedded-themes.md)
* [Migration / Updates](migration.md)
Basic Concepts
------------------
* [Introduction](modules-index.md)
* [Basic Structure](modules-structure.md)
* [Migration/Updates](modules-migrate.md)
* [Content](modules-content.md)
* [Users](modules-users.md)
* [Events](modules-events.md)
* [Settings and Configuration](modules-settings.md)
* [Models / Database](modules-db.md)
* [Models / Database](modules-db.md)
* [Internationalization](modules-i18n.md)
* [Content](content.md)
* [Streams](stream.md)
* [Events](events.md)
* [Settings and Configuration](settings.md)
* [Models / Database](models.md)
* [Permissions](permissions.md)
* [Notifications](notifications.md)
* [Activities](activities.md)
* [File Handling](files.md)
* [Widgets](widgets.md)
* [Snippets](snippet.md)
* [Internationalization](i18n.md)
Javascript API
------------------
* [Modules](javascript-index.md)
* [Components](javascript-components.md)
* [Additions](javascript-uiadditions.md)
* [Additions](javascript-components.md)
* [Actions](javascript-actions.md)
* [Client](javascript-client.md)
* [Modals](javascript-modals.md)
* [Events](javascript-events.md)
* [Widgets](javascript-widgets.md)
* [Pjax](javascript-pjax.md)
Special Topics
Advanced Topics
--------------
* [Notifications](notifications.md)
* [Activities](activities.md)
* [HumHub Build](build.md)
* [Authentication](authentication.md)
* [Events](events.md)
* [Live Updates](live.md)
* [Search](search.md)
* [Security](security.md)
* [Console Application](console.md)
* [Streams](stream.md)
* [Permissions](permissions.md)
* [Widgets](widgets.md)

View File

@ -0,0 +1,5 @@
Asset Management
=====================
(TBD)
(TBD:getPublishedUrl)

View File

@ -0,0 +1,63 @@
HumHub Build
============
## Setup
1. Install NPM
2. Install Grunt (http://gruntjs.com/getting-started)
3. call `npm update` in humhub root
> Note: Since symlinks are not supported in some virtual machine shared folders the update command should be called from the host.
## Setup grunt dependencies
Call the following commands in your humhub root directory:
- `npm update`
- `npm install grunt --save-dev`
## Build Assets
HumHub uses Yiis build in mechanism for compressing and combining assets as javascript or stylesheet files in combination with grunt.
Your compressed files will be saved under `/humhub/js/all-*.js` respectively `static/css/all-*.css`.
> Note: HumHub will only use the compressed assets if operated in [production mode](admin-installation.md#disable-errors-debugging), otherwise
all assets will be served seperatly.
### Grunt Asset Built
The simples way to build your production assets is using the following grunt task:
```
grunt build-assets
```
### Manual Asset Built
1. Delete the content of your `static/assets` directory.
2. Delete the old compressed file `static/js/all-*.js` and `static/css/all-*.css`
2. Run:
```
php yii asset humhub/config/assets.php humhub/config/assets-prod.php
```
> Info: More information is available in the [Yii Asset Guide](http://www.yiiframework.com/doc-2.0/guide-structure-assets.html#combining-compressing-assets).
## Build Community Theme
To rebuild the community themes `theme.css` file you can execute one of the following commands:
```
lessc -x themes/HumHub/less/build.less themes/HumHub/css/theme.css
```
or with grunt:
```
grunt build-theme
```
### Other Grunt Tasks
- `grunt build-search` Rebuild your [Search Index](../admin/search.md)

View File

@ -0,0 +1,280 @@
Content
=======
Content record classes as for example `Post`, `Poll` and `Wiki` are subclasses of
[[\humhub\modules\content\components\ContentContainerActiveRecord]].
Instances ofand are related to a
[[humhub\modules\content\models\Content]] record.
A ContentContainerActiveRecord subclass provides all features of a basic
Yii [ActiveRecords](http://www.yiiframework.com/doc-2.0/yii-db-activerecord.html) as validation and data access methods,
please refer to the [Yii Guide](http://www.yiiframework.com/doc-2.0/guide-db-active-record.html) for more information
about [ActiveRecords](http://www.yiiframework.com/doc-2.0/yii-db-activerecord.html).
While the ContentContainerActiveRecord class contains the actual content data as texts and content settings, the related Content instance is beside others used to check **Permissions**, the **ContentContainer** relation, content **visibility** and is furthermore connected to ContentAddons as Like and Comments.
Beside the basic ActiveRecord methods your ContentContainerActiveRecord class should at least implement the following functions
- `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.
```php
class Example extends \humhub\modules\content\components\ContentContainerActiveRecord
{
public static function tableName()
{
return 'example_content';
}
public function getContentName()
{
return Yii::t('ExampleModule.models_Example', "Example");
}
public function getContentDescription()
{
return $this->question;
}
public function rules()
{
//return validation rules
}
.....
}
```
Your content model should be **instantiated** as follows:
```php
// Instantiate my model assign a content container and visibility.
$model = new MyModel();
$model->content->container = $someSpace;
$model->content->container = Content::VISIBILITY_PRIVATE;
...
// Save model and content
$model->save();
```
Get the model instance from a given content instance:
```php
$model = $content->getPolymorphicRelation();
```
Calling [[\humhub\modules\content\components\ContentActiveRecord::find()]] will return a [[\humhub\modules\content\components\ActiveQueryContent]] with additional methods to select specific content:
```php
// 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_SCOPE_OWN` Content created by the given user itself (`content.created_by`)
- `USER_RELATED_SCOPE_SPACES` Content related to the users member spaces
- `USER_RELATED_SCOPE_FOLLOWED_SPACES` = Content related to the users followed spaces
- `USER_RELATED_SCOPE_FOLLOWED_USERS` = Content related to the users followed user profiles
- `USER_RELATED_SCOPE_OWN_PROFILE` = Content related to the users own profile
### Content features
**Content visibility**
The content visibility can be checked by calling `isPublic()` and `isPrivate()`.
```php
$model->content->isPublic();
$model->content->isPrivate();
// Set visibility
$model->content->container = Content::VISIBILITY_PRIVATE;
```
**Pin content**
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.
```php
$model->content->pin();
$model->content->unpin();
$model->content->isPinned();
$model->content->canPin();
```
**Archive content**
Archived content is by default excluded from the streams. As with the pin logic, you won't have to handle this by yourself.
```php
$model->content->archive();
$model->content->unarchive();
$model->content->isArchived();
$model->content->canArchive();
```
**Content Url**
By default the `Content::getUrl()` returns the permalink of the wallentry. In case the content is used outside of the default stream, this behaviour can be changed by implementing a `getUrl()` method in your ContentActiveRecord class.
```php
$permaLink = $model->content->getUrl();
```
### Check content permissions
By default a user can edit a content if one of the following conditions defined in `Content::canEdit()` are met:
- User is the owner of the content
- User is system administrator and the content module setting `adminCanEditAllContent` is set to true (default)
- The user is granted the space ManagePermission set by the model record class. Since v1.2.1 a ContentContainerActiveRecord can define an own `$managePermission` which will be described later.
- The user meets the additional condition, which is defined in the ContentContainerActiveRecords `canEdit()` function.
You can check the edit permission of a user by means of the `Content::canEdit()` function as
```php
// Check edit permission for current logged user
if($model->content->canEdit()) {...}
// Check edit permission for a given user
if($model->content->canEdit($someUserIdentity)) {...}
// Check other permission for the current logged user on the contents contentContainer
if($model->content->can(new MyCustomPermission()) {...}
```
Since HumHub v1.2.1 you can overwrite the default ManageContent permission as follows:
```php
class Example extends ContentContainerActiveRecord
{
$managePermission = MyCustomManagePermission::class;
.....
}
```
The default `Content::canView()` permission behaviour of content is handled as follows
- Guests can only access public content of visible spaces/users
- Other users can access all public content within the network
- System admins can access all content if the `adminCanViewAllContent` setting of the `content` modules is enabled (default)
- All space members can access private space content
- Non space members can only access public space content
- Only friend users can access prviate profile content of a user.
```php
if($model->content->canView()) {...}
```
>Info: For more information about permissions, please see the [Permission Section](module-permissions.md).
## ContentContainer
A [[humhub\modules\content\models\ContentContainer|ContentContainer]] in HumHub is the base concept for assigning content entries to a specific container instance (user or space).
Each [[humhub\modules\content\models\ContentContainer|ContentContainer]] is assigned with an unique guid, which is used in controllers to identify the context of its actions.
Currently there are two types of ContentContainer:
- [[humhub\modules\user\models\User|User]]
- [[humhub\modules\space\models\Space|Space]]
![Application Layers](images/contentContainerClassDiag.jpg)
> Note: It's not possible to create own ContentContainer classes, yet.
### ContentContainerController
The [[humhub\modules\content\components\ContentContainerController|ContentContainerController]] class is extended by controllers working in the context of a specific [[humhub\modules\content\models\ContentContainer|ContentContainer]].
A [[humhub\modules\content\components\ContentContainerController|ContentContainerController]] will automatically search for a **sguid** (Space) or **uguid** (User) request parameter in every request and will instantiate the corresponding [[humhub\modules\content\models\ContentContainer|ContentContainer]].
The [[humhub\modules\content\components\ContentContainerController|ContentContainerController]] provides common tasks like:
- Automatic container loading based on URL
- Access checks
- Layout selection based on container type (User or Space)
- Create URL's for the given ContentContainer
```php
class ExampleController extends \humhub\modules\content\components\ContentContainerController
{
public function actionIndex()
{
if ($this->contentContainer instanceof Space) {
//Space related stuff...
}
}
}
```
Urls pointing to a ContentContainer action should be created by using the `createUrl()` function of your ContentContainer instance. This will add the required sguid or uguid to your request.
```php
// Direct ContentContainer call
$space->createUrl('/module/controller/action');
// Within a ContentContainerController:
$this->contentContainer->createUrl('/module/controller/action');
```
> Note: Requests for a [[humhub\modules\content\components\ContentContainerController|ContentContainerController]] action without providing a sguid or uguid parameter will fail!
### ContentContainerActiveRecord
Each ContentContainer class is derived from [[\humhub\modules\content\components\ContentContainerActiveRecord]].
Beside others, this abstract class provides the following functionality:
- [Permission Management](dev-permissions.md) `getPermissionManager()`
- Profile-/Banner-image access `getProfileImage()`, `getProfileBannerImage()`
- Rendering the container stream `getWallOut()` (see [Permission Management](dev-stream.md))
Profile image example:
```php
//Get Profile Image Url
$profileImage = $space->getProfileImage();
if($profileImage->hasImage()) {
$url = $profileImage->getUrl();
}
```
### ContentContainerModule
See the [Getting Started](modules-index.md) section
#### Content Streams
See the [Stream](stream.md) section
## Global content
(TBD)
## Content addons
TBD
- Always linked to particual Content, inherits access rules from it
- Examples: Like, File, Comment
- Can be nested (e.g. Container -> Content -> Addon (Comment) -> Addon (Like)

View File

@ -1,3 +1,24 @@
# Contributing
TBD
## Report an Issue
**Do not report an issue if**
- *you are asking how to use a HumHub feature. You should use [the community](https://community.humhub.com) for this purpose.*
- *your issue is about security. Please [contact us directly](mailto:info@humhub.com) to report security issues.*
**Avoid duplicated issues**
Before you report an issue, please search through [existing issues](https://github.com/buddh4/humhub-docs/issues) to see if your issue is already reported or fixed to make sure you are not reporting a duplicated issue.
Also make sure you have the latest version of HumHub and see if the issue still exists.
## Contribute to the Docs or fix grammar errors (Pull Requests)
Third-party patches are essential for keeping the HumHub Docs great.
We want to keep it as easy as possible to contribute changes that get things working in your environment.
There are a few guidelines that we need contributors to follow so that we can have a chance of keeping on top of things.
- *Make sure you have a [GitHub account](https://github.com/signup/free)*
- *Fork the repository on GitHub*
- *Make sure there isn't an issue created for the thing you are working on if it requires significant effort to fix*
- *Open a pull request*

View File

@ -0,0 +1,2 @@
Embedded themes
=================

View File

@ -4,50 +4,53 @@ Development Environment
Quick Notes
-----------
- Make sure you are using a [Git/Composer HumHub Installation](git-installation.md)
- Enable development mode, see [Disable Errors Section](../admin/security.md#disable-errors-debugging)
- Disable Caching under `Administration -> Settings -> Advanced -> Caching -> None`
- Make sure you are using a [Git/Composer HumHub installation](git-installation.md)
- Enable the debug mode, see [Disable Errors Section](../admin/security.md#disable-errors-debugging)
- Disable caching under `Administration -> Settings -> Advanced -> Caching -> None`
> Tip: If you are working on a windows machine, but wan't to operate your test environment on linux, you should consider using a virtual machine with a shared host directory.
Modules Directory
External Modules Directory
-----------------
You can locate your custom modules outside of the HumHub project directory by means of the following [configuration](../admin/advanced-configuration.md#application-params)
Custom modules can also be located outside of the default HumHub modules directory by
setting the `moduleAutoloadPaths` parameter in your `/protected/config/common.php` configuration. This seperation can
be useful while working with custom modules.
```php
return [
//...
'params' => [
'moduleAutoloadPaths' => ['/some/folder/modules'],
]
],
//...
]
```
Yii Debug Module
----------------
Add the following block to your local web configuration `/protected/config/web.php` to enable the [Debug Extension for Yii 2](http://www.yiiframework.com/doc-2.0/ext-debug-index.html)
Add following block to your local web configuration `/protected/config/web.php` in order
to allow [Yii's debug Module](http://www.yiiframework.com/doc-2.0/ext-debug-index.html).
```php
<?php
return [
// ...
'bootstrap' => ['debug'],
'modules' => [
'debug' => [
'class' => 'yii\debug\Module',
'allowedIPs' => ['127.0.0.1', '::1'],
],
]
'modules' => [
// ...
'debug' => [
'class' => 'yii\debug\Module',
'allowedIPs' => ['127.0.0.1', '::1'],
],
// ...
]
];
?>
```
Gii Code Generator
-------------------
Add following block to your local web configuration `/protected/config/web.php` to enable the [Gii Code Generator](http://www.yiiframework.com/doc-2.0/guide-start-gii.html)
Add following block to your local web configuration `/protected/config/web.php` in order to
enable the [Gii Code Generator Module](http://www.yiiframework.com/doc-2.0/guide-start-gii.html)
```php
return [
@ -64,7 +67,7 @@ return [
?>
```
Furthermore add the following block to your local console configuration (/protected/config/console.php)
Furthermore add the following block to your local console configuration `/protected/config/console.php`
```php
return [
@ -77,76 +80,7 @@ return [
];
```
> Tip: Check out the [HumHub devtools](https://github.com/humhub/humhub-modules-devtools) module for a HumHub module generator and some showcases and tutorials. At the time of writing, the devtools Module is still under developement.
HumHub Build
-----------
Some of the tasks
### Setup
1. Install NPM
2. Install Grunt (http://gruntjs.com/getting-started)
3. call `npm update` in humhub root
> Note: Since symlinks are not supported in some virtual machine shared folders the update command should be called from the host.
#### Setup grunt dependencies
Call the following commands in your humhub root directory:
- `npm update`
- `npm install grunt --save-dev`
### Build Production Assets
HumHub uses Yiis build-in mechanism for compressing and combining assets as javascript or stylesheet files in combination with grunt.
Your compressed files will be saved under `/humhub/js/all-*.js` respectively `static/css/all-*.css`. The task will also rebuild your `static/assets` folder, which contains dependent production assets.
> Info: HumHub will only use the compressed assets if operated in [production mode](admin-installation.md#disable-errors-debugging), otherwise all assets will be served seperatly.
##### Grunt Asset Built
The simples way to build your production assets is using the following grunt task:
```
grunt build-assets
```
##### Manual Asset Built
1. Delete the content of your `static/assets` directory.
2. Delete the old compressed file `static/js/all-*.js` and `static/css/all-*.css`
2. Run:
```
php yii asset humhub/config/assets.php humhub/config/assets-prod.php
```
> Info: More information is available in the [Yii Asset Guide](http://www.yiiframework.com/doc-2.0/guide-structure-assets.html#combining-compressing-assets).
### Build Theme
To rebuild the community themes `theme.css` file you can execute one of the following commands:
```
lessc -x themes/HumHub/less/build.less themes/HumHub/css/theme.css
```
or with grunt:
```
grunt build-theme
```
You can also build other themes within your `themes` folder as follows
```
grunt build-theme --name=myTheme
```
### Other Grunt Tasks
- `grunt build-search` Rebuild your [Search Index](../admin/search.md)
Developer Tools Module
-------------------
The [devtools Module](https://github.com/humhub/humhub-modules-devtools) provides useful showcases of widgets and also a Module generator based on Gii.

View File

@ -0,0 +1,41 @@
Events
======
TBD
[http://www.yiiframework.com/doc-2.0/guide-concept-events.html](http://www.yiiframework.com/doc-2.0/guide-concept-events.html)
### Catching an Event
Example event section of the config.php file:
```php
// ...
'events' => [
[
'class' => \humhub\widgets\TopMenu::className(),
'event' => \humhub\widgets\TopMenu::EVENT_INIT,
'callback' => [Module::className(), 'onTopMenuInit'],
],
// ...
]
// ...
```
### Processing
Example of event callback:
```php
public static function onTopMenuInit($event)
{
$event->sender->addItem(array(
'label' => "Example",
'icon' => '<i class="fa fa-tachometer"></i>',
'url' => '#',
'sortOrder' => 200,
));
}
```

View File

@ -1,11 +1,9 @@
Git Installation (Developers)
Installation (Developers)
=========================
> Warning: This installation method allows you to fetch the latest version from our git repository. Since the master branch is not always in a stable state, this branch is not intended for production use.
> Warning: This installation method allows you to fetch the latest branch from the repository which may not stable enough for production use.
Preparation
-----------
Create a MySQL Database, e.g.:
```sql
@ -16,52 +14,23 @@ FLUSH PRIVILEGES;
> Note: Do not forget to change the `humhub_dbuser` and `password_changeme` placeholders!
Get HumHub
----------
In order to be able to install a branch fetched by git, you'll have to run a composer update to download external dependencies.
1. Clone Git Repository:
- Install [git](https://git-scm.com/)
- Clone git Repository:
```
git clone https://github.com/humhub/humhub.git
```
2. Install composer ([https://getcomposer.org/doc/00-intro.md](https://getcomposer.org/doc/00-intro.md))
3. Navigate to your HumHub webroot and fetch dependencies:
- Install composer ([https://getcomposer.org/doc/00-intro.md](https://getcomposer.org/doc/00-intro.md))
- Navigate to your HumHub webroot and fetch dependencies:
```
php composer.phar install
php composer.phar global require "fxp/composer-asset-plugin:~1.3"
php composer.phar update
```
> Note: The composer update may have to be executed again after an update of your local repository by a git pull. Read more about updating ([Update Guide](admin-updating.html#gitcomposer-based-installations))
File Settings & Permissions
---------------------------
Make the following directories/files writable by the webserver
- /assets
- /protected/config/
- /protected/modules
- /protected/runtime
- /uploads/*
Make the following files executable:
- /protected/yii
- /protected/yii.bat
> Warning: Make sure the following directories are not accessible through the webserver!
Start Web Installer
---------------
Open the installation guide in your browser (e.g. [http://localhost/humhub](http://localhost/humhub))
> Note: The composer update may have to be executed again after an update of your local repository by a git pull. Read more about updating ([Update Guide](../admin/updating.md))
- Follow further instructions of the [Installation Guide](../admin/installation.md)

View File

@ -0,0 +1,28 @@
Internationalization (I18N)
===========================
**Optionally** you can use following module translation method instead of Yii's standard approach (<http://www.yiiframework.com/doc-2.0/guide-tutorial-i18n.html#translating-module-messages>).
For Internationalization to work properly, you should also consider the notes on [Setting Up PHP Environment](http://www.yiiframework.com/doc-2.0/guide-tutorial-i18n.html#setup-environment)
from the Yii Guide.
### Message Category
Following message category syntax is automatically mapped against your modules *messages* folder.
```php
Yii::t('ExampleModule.some_own_category', 'Translate me');
```
Base Category Naming Examples:
- polls -> PollsModule
- custom_pages -> CustomPagesModule
### (Re-) Generate message files
Example message creation command for module with id *example*:
> php yii message/extract-module *example*

View File

@ -1,7 +1,7 @@
Javascript UI Components
=======
UI Components can be used to bind specific parts of your view to a Javascript Widgets defined in your module. This can be achieved by extending the `action.Component` or the more powerful `ui.Widget` class.
UI Components can be used to bind specific dom parts of your view to a Javascript Widgets defined in your module. This can be achieved by extending the `action.Component` or the more powerful `ui.Widget` class.
## Simple Components
@ -29,13 +29,13 @@ humhub.module('example.MyComponent', function(module, require, $) {
Component.call(this, node, options);
}
// Make sure this is called before your function definitions, otherwise they will be lost!
object.inhertis(MyComponent, Component);
MyComponent.prototype.hello = function(evt) {
this.$.find('.message').text('Hi!');
}
// Export a single class
module.export = MyComponent;
});
```
@ -46,7 +46,7 @@ After clicking the button of the previous example the `action` module will searc
If you need the instance of your component, for example in another module, you can retrieve it by calling `Component.instance`:
```javascript
```Javascript
humhub.module('example.two', function(module, require, $) {
var Component = require('action').Component;
@ -75,12 +75,12 @@ Components can be nested, which can be handy for example if you want to implemen
###### Module:
```javascript
```Javascript
humhub.module('example.mylist', function(module, require, $) {
var object = require('util').object;
var Component = require('action').Component;
// our parent component
// our parent component
var List = function(node, options) {
Component.call(this, node, options);
}
@ -115,22 +115,21 @@ humhub.module('example.mylist', function(module, require, $) {
});
});
```
> Note: The `data` function of a component will search for a given data attribute on the components own root node and if not present will search the parent components for the data attribute.
## Widgets
The `humhub.modules.ui.widget.Widget` class extends the `action.Component` class and provides some additional functionality as:
The `humhub.modules.ui.widget.Widget` class extends the `Component` class and provides some additional functionality as:
- Advanced event handling
- Eager initialization
- Eager or lazy initialization
- Widget options
#### Widget Initialization
A Widgets `init` function is called once the widget is created. A Widget is created either immediately within the humhub initialization phase in case the widgets root node contains a `data-ui-init` flag or lazily by calling a widget action or initializing the Widget by means of calling `Widget.instance('#myWidget')`.
A Widgets `init` function is called once the widget is created. A Widget is created either immediately within the humhub initialization phase in case the widgets root node contains a `data-ui-init` flag or by lazily creating it when calling a widget action or initializing the Widget by means of calling `Widget.instance('#myWidget')`.
> Note: If you load a Widget by an ajax call, make sure to apply the [ui.additions](javascript-uiadditions.md) on your inserted dom node, otherwise the `data-ui-init` behaviour won't be recognized.
> Note: If you load a Widget by an ajax call, make sure to apply the `ui.additions` on your inserted dom nodes, otherwise the `data-ui-init` behavriour won't be recognized.
###### View:
```php
@ -157,13 +156,14 @@ humhub.module('example.MyWidget', function(module, require, $) {
this.$.fadeIn('fast');
}
// Export a single class
module.export = MyWidget;
});
```
#### Widget Options
Your Widget options can be set by using `data-*` attributes on your Widgets root node.
Your widgets option can be set by using `data-*` attributes on your Widgets root node.
The Widgets `getDefaultOptions()` method can be used to define default Widget options.
###### View:
@ -184,6 +184,7 @@ humhub.module('example.MyWidget', function(module, require, $) {
Widget.call(this, node, options);
}
// Make sure this is called before your function definitions, otherwise they will be lost!
object.inhertis(MyWidget, Widget);
var MyWidget.prototype.getDefaultOptions = function() {
@ -200,6 +201,7 @@ humhub.module('example.MyWidget', function(module, require, $) {
}
}
// Export a single class
module.export = MyWidget;
});
```
@ -211,9 +213,26 @@ TBD
#### JsWidget class
In order to implement a Yii widget responsible for rendering your widgets markup, you can extend hte [[humhub\widgets\JSWidget]] class as in the following examples.
In order to implement a Yii widget responsible for rendering your widgets markup, you can implement a PHP class derivated of [[humhub\widgets\JSWidget]] as in the following examples.
##### Default widget rendering:
Here are some of the available attributes of the JSWidget class:
- `id`: the widget root id, if not provided a generated id will be used by default
- `jsWidget`: defines the Javascript widget namespace
- `init`: will add the data-ui-init flag if set to true
- `visible`: can be set to false in case the root node should be rendered hidden on startup
- `options`: used to overwrite or set the Widgets htmlOptions
- `events`: defines widget action events
- `container`: defines the root node name when using the default rendering mechanism
- `content`: defines the content of the root node when using the default rendering mechanism
Functions:
- `getData()`: returns an array of widget settings which will be transformed into `data-*` attributes.
- `getAttributes()`: returns an array of html attributes/values
- `getOptions()`: merges the given `options` with the result of `getData()` and `getAttributes()` and is used as root node options in most of the cases
###### Default widget rendering:
The following example shows a simple JsWidget implementation without overwriting the widgets `run` method.
@ -248,24 +267,6 @@ class MyWidget extends \humhub\widgets\JsWidget
}
}
```
The following `JSWidget` attributes are available:
- `id`: the widget root id, if not provided a generated id will be used by default
- `jsWidget`: defines the Javascript widget namespace
- `init`: will add the data-ui-init flag if set to true
- `visible`: can be set to false in case the root node should be rendered hidden on startup
- `options`: used to overwrite or set the Widgets htmlOptions
- `events`: defines widget action events
- `container`: defines the root node name when using the default rendering mechanism
- `content`: defines the content of the root node when using the default rendering mechanism
Functions:
- `getData()`: returns an array of widget settings which will be transformed into `data-*` attributes.
- `getAttributes()`: returns an array of html attributes/values
- `getOptions()`: merges the given `options` with the result of `getData()` and `getAttributes()` and is used as root node options in most of the cases
> Note: in this case the `container` setting could be omitted, since `div` is the default container name.
The widget could be used within a view as follows:
@ -285,7 +286,7 @@ which would render the following output:
<div class="myWidget" data-some-setting="0" data-ui-init="1">Some content</div>
```
##### Custom widget rendering:
###### Custom widget rendering:
For more complex JsWidgets, you can overwrite your widgets `run` method and use the `getOptions` method to merge the widgets `options` with the default options provided by `getData` und `getAttributes` as follows.

View File

@ -1,18 +1,19 @@
Javascript Modules
Javascript API Getting Started
=======
Since version 1.2, HumHub provides a module based Javascript API within the `humhub` namespace.
Instead of embeding inline script blocks into your views, it's highly recommended to store your Javascript code in external script files and ideally use the HumHub module system.
Your module scripts should reside in the `resources/js` directory of your modules root directory.
Instead of embeding inline script blocks into your views, it's highly recommended to store your Javascript code in external script files and use the HumHub module system.
## Modules System
### Publish a Module Asset
In order to add your script files to your view, you should use an [Asset Bundle](http://www.yiiframework.com/doc-2.0/guide-structure-assets.html) residing within the `assets` directory of your module.
Your script files should reside within the `resources/js` folder of your humhub module and should ideally be appended at the bottom of the document.
In order to add a Javascript module file to your view, you should use a [Asset Bundle](http://www.yiiframework.com/doc-2.0/guide-structure-assets.html) class residing within the `assets` directory of your module. By setting `public $jsOptions = ['position' => \yii\web\View::POS_END];`, your assets will be appended to the end of the document body. This will assure all core modules are already registered.
Be careful though, when you want to edit your files in `resources/js`. All asset files are bundled and then copied to the `@webroot`-folder of your application, when registered in the view for the first time (see below). In order to force your module assets to be re-published with each requests, you can add the publish option `forceCopy` as in the following example. This can be useful while developing your module, but don't forget to disable this option in official releases!
By setting `public $jsOptions = ['position' => \yii\web\View::POS_END];`, your assets will be appended to the end of the document body. This will assure all core modules are already registered. If you require your script beeing loaded ealrier you can also set `\yii\web\View::POS_BEGIN`, which will add you script at the beginning of the document body.
```php
namespace humhub\modules\example\assets;
@ -21,6 +22,9 @@ use yii\web\AssetBundle;
class ExampleAsset extends AssetBundle
{
public $publishOptions = [
'forceCopy' => true
];
public $jsOptions = ['position' => \yii\web\View::POS_END];
public $sourcePath = '@example/resources';
public $js = [
@ -37,24 +41,23 @@ The [Asset Bundle](http://www.yiiframework.com/doc-2.0/guide-structure-assets.ht
Where `$this` is the view instance. More infos about Asset Bundles are available in the [Yii Guide](http://www.yiiframework.com/doc-2.0/guide-structure-assets.html).
If your bundle is registered to a view retrieved by an ajax call, make sure to render your view by using your controllers `$this->renderAjaxContent()` function. In contrast to `renderPartial()`, this function will add all your asset dependencies to your partial content.
> Note: Make sure to add your assets after the core scripts, which are added within the documents head section.
> Note: Yii loads Javascript Files only once per page load, therefore all your script files will only be loaded and executed once. This can lead to unexpected behaviour especially with [Pjax](javascript-client.md#pjax) single page loading enabled.
> Note: If your bundle is registered to a view retrieved by an ajax call, make sure to render your view by using your controllers `$this->renderAjaxContent()` function. In contrast to `renderPartial()`, this function will add all your asset dependencies to your partial content. Don't use the `renderAjaxContent` to include a view into your page outside of an ajax call, this will include some script twice and will lead to unexpected behaviour.
> Note: Yii loads Javascript Files only once per page load, therefore all your script files will only be loaded and executed once. This can lead to unexpected behaviour especially with [Pjax](javascript-client.md) single page loading enabled.
### Register Modules
Modules are registered by calling the `humhub.module()` function as follows
Modules are registered by calling the `humhub.module` function as follows
```javascript
humhub.module('example', function(module, require, $) {
...
});
```
The previous `example` module will be added to the following namespace `humhub.modules.example`.
You can also register sub modules as in the following example
**Submodules** can be registered as follows
```javascript
humhub.module('example.mySubModule', function(module, require, $) {
@ -62,9 +65,9 @@ humhub.module('example.mySubModule', function(module, require, $) {
});
```
The first argument of the `humhub.module()` function defines the **module id** which also defines the namespace appended to the `humhub.modules`. The second argument is the actual **module function**.
The first argument of the `humhub.module` function defines the **module id** which will be appended to the `humhub` namespace. The previous `example` module will be added to the following namespace `humhub.modules.example`. The second argument is the actual **module function**.
> Note: You should use an unique namespace for your custom modules as `myproject.mymodule`, otherwise it may interfere with other modules.
> Note: Your module id has to be unique amongst all available modules and should ideally be consistent with your backend module id.
Your module function is provided with the following arguments:
@ -72,18 +75,15 @@ Your module function is provided with the following arguments:
2. `require` - Used for injecting other modules.
3. `$` - jQuery instance.
#### Export Module Logic
##### Export Module Logic
Module functions and attributes can only be accessed outside of the module if they are exported, either by directly appending them to the `module` instance or by calling `module.export`.
```javascript
humhub.module('example', function(module, require, $) {
// private function
var private = function() { /* ... */ }
// direct export of public function
module.publicFunction = function() {/* ... */}
// export public function
module.myPublicFunction = function() {/* ... */}
// another public function exported later
var publicTwo = function() { /* ... */}
@ -95,27 +95,28 @@ humhub.module('example', function(module, require, $) {
});
});
```
In case you only want to **export a single object/function/class** you can use the following syntax:
```javascript
/* ... */
[...]
var MyClass = function() {/*...*/};
MyClass.prototype.myFunction = function() {/*..*/}
module.export = MyClass;
/* ... */
[...]
```
> Note: When exporting a single object or class, the plain object or function will be added to the given namespace without including the usual module attributes and utilities mentioned later in this guide.
> Note: When exporting a single object or class, the exported object won't have the usual module attributes and utilities. The plain object or function will simply be added to the namespace.
#### Module Initialization
##### Module Initialization
Your module can define its initialization logic by exporting an `init` function.
Your module can define its initialization logic by implementing and exporting an `init` function.
By default this function is only called once after a full page load or directly after the registration in case the module was loaded per ajax. If your module requires an initialization also after [Pjax](javascript-client.md) page loads, your module has to set the `initOnPjaxLoad` flag. In this case the `init` function will provide an `isPjax` flag for beeing able to distinguish between full page loads and [Pjax](javascript-client.md) page loads.
By default this function is only called once after a full page load or directly after the registration in case the module was loaded per ajax. If your module requires an initialization also after [Pjax](javascript-client.md) page loads, your module has to set the `initOnPjaxLoad` flag. In this case the `init` function will provide an `isPjax` parameter for beeing able to distinguish between full page loads and [Pjax](javascript-client.md) page loads.
```javascript
/* ... */
[...]
module.initOnPjaxLoad = true;
var init = function(isPjax) {
@ -130,15 +131,14 @@ var init = function(isPjax) {
module.export({
init: init
});
/* ... */
[...]
```
> Tip: You'll need the `initOnPjaxLoad` flag for modules which rely on specific dom elements or specific views.
> Warning: Once registered, your modules `init` function may be called even if you are not currently in your desired modules view. This occures especially if [Pjax](javascript-pjax.md) is enabled and `initOnPjaxLoad` is set to `true`. Therfore, if your modules initialization logic only makes sense in a specific context, make sure you reside in the desired view before running your actual initialization code e.g: `if(!$('#mySpecialViewElement').length) {return;}`.
> Warning: Once registered, your modules `init` function may be called even if you are not currently in your desired modules view. This occures especially if [Pjax](javascript-pjax.md) is enabled and `initOnPjaxLoad` is set to `true`. Therfore, if your modules initialization logic only makes sense in a specific context, make sure you reside in the desired view before running your actual initialization code e.g: `if(!$('#mySpecialElement').length) {return;}`.
#### Module Unload
##### Module Unload
For the purpose of cleaning up module related dom nodes etc. your module can export an `unload` function which is called before each Pjax page load. This function is mainly used to remove obsolete dom nodes outside of the main content area, prevent memory leaks, remove obsolete dom listeners or clear up some module data.
For the purpose of cleaning up module related dom nodes etc. there is also an `unload` function which is called before each Pjax page load. This function is mainly used to remove obsolete dom nodes, prevent memory leaks, remove obsolete dom listeners or clear some module data.
```javascript
var unload = function($pjax) {
@ -152,7 +152,7 @@ module.export({
> Note: Some third party libraries append helper elements to the document body. Make sure to remove such elements in the `unload` function.
#### Module Dependencies
##### Module Dependencies
Other modules can be injected into your module by using the `require` function as follows
@ -169,7 +169,7 @@ require('example').myFunction();
humhub.modules.example.myFunction();
```
It's good practice to require all dependent modules at the beginning of your module. When doing so consider the loading order of those modules. Since all core modules are registered in the head section of your document, they are available within the document body.
It is a good practice to require all dependent modules at the beginning of your module. You should only require modules at the beginning of your module, if you are sure the required module is already registered. Since all core modules are registered in the head section of your document, they are available within the document body.
If your module requires another module, which is not part of the core API, you can ensure the order by means of the `$depends` attribute of your Asset Bundle class.
@ -180,9 +180,7 @@ public $depends = [
];
```
> Note: You can only `depend` Assets with a higher or equal `$jsOption position`.
In case you can't assure the registration order of a required module, but need to import the module, you can either require the module on demand within your module function or use the `lazy` flag of the require function.
In case you can't assure the module registration order of a required module, but need to import the module, you can either require the module on demand within your module function or use the `lazy` flag of the require function.
The call to `require('anotherModule', true)` will return an empty namespace object in case the dependent module has not been registered yet. The actual module logic will be available after the dependent module is registered.
@ -207,7 +205,7 @@ humhub.module('example', function(module, require, $) {
});
```
> Info: All core modules are appended to the head section of your document, so there should not be any dependency problem for those modules if you append your assets either at the begin or the end of the document body.
> Info: All core modules are appended to the head section of your document, so they should not be any dependency problem if you append your assets either at the begin or the end of the document body.
### Module Lifecycle
@ -218,7 +216,7 @@ A module runs through the following lifecycle (by the example of our `example` m
3. **Document Ready**
4. `humhub:beforeInitModule`
5. `humhub:modules:example:beforeInit`
6. Calling the modules `init` function with `isPjax = false`
6. Calling the modules `init` function
7. `humhub:modules:example:afterInit`
8. `humhub:afterInitModule`
9. `humhub:ready`
@ -227,7 +225,6 @@ A module runs through the following lifecycle (by the example of our `example` m
12. Calling the modules `unload` function
13. `humhub:modules:client:pjax:success`
14. Reinitialize all modules with `initOnPjaxLoad=true` by calling `init` with `isPjax = true`
15. `humhub:ready`
### Module Configuration
@ -238,7 +235,7 @@ humhub.module('example', function(module, require, $) {
...
var myAction = function() {
if(module.config.showMore) {
if(module.config['showMore']) {
// Do something
}
};
@ -262,7 +259,7 @@ $this->registerJsConfig([
);
```
Setting configurations in Javascript:
Setting configurations in javascript:
```javascript
// Set config values for multiple modules
@ -294,12 +291,12 @@ Beside the `config` array, the module instance furthermore provides a `text` uti
//Configurate your text in your php view.
$this->registerJSConfig('example', [
'text' => [
'error.notallowed' => Yii::t('ExampleModule.views_example', 'You are not allowed to access example!');
'error.notallowed' => Yii::t('ExampleModule.views.example', 'You are not allowed to access example!');
]
]);
```
Access your text as
Access your text within your js module as this
```javascript
module.text('error.notallowed');
@ -344,7 +341,7 @@ module.log.error('error.default', new Error('xy'), true);
The trace level of your module can be configured by setting the `traceLevel` configuration. If your module does not define an own trace level the log modules's traceLevel configuration will be used instread. In production mode the default log level is set to `INFO`, in dev mode its set to `DEBUG`.
> Info: Your module logger will try to resolve a given text key to a module or global text configuration.
> Info: Your module logger will try to resolve a given text key to a module or global text.
> Info: The `module.log.success()` function will trigger a status bar update by default.

View File

@ -0,0 +1,3 @@
Live Updates
=================
(TBD)

View File

@ -0,0 +1,100 @@
# Module Migration Guide
Here you will learn how you can adapt existing modules to working fine with actually versions.
## 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](files.md) 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
### Javascript API changes
TBD
#### Pjax + TopNavigation:
Use
public $topMenuRoute = '/dashboard/dashboard';
within your controller for pjax topmenu support.
### Asset Handling changes
TBD
## 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](settings.md) 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](old/modules-migrate-0.20.md)
## 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

View File

@ -0,0 +1,7 @@
Module - Migration
=================
## Installation
## Uninstallation
## Compatibility
(TBD)

View File

@ -0,0 +1,87 @@
(TBD:getPublishedUrl)Database and Models
====================
## Conventions
- prefix your tables with the module id. e.g. example_foo
- singular table names
- use underscorce in fieldnames/attributes e.g. user_id
## ActiveRecord (Model)
To be able to provide persistent data a module has to implement model class derived from [[humhub\components\ActiveRecord]].
Yii follows the concept of rich models, which means a model class can contain content in form of attributes as well as domain logic.
More information about the use of ActiveRecords is available in the [Yii2 guide](http://www.yiiframework.com/doc-2.0/guide-db-active-record.html).
> Info: [[humhub\components\ActiveRecord]] is derived from [[yii\db\ActiveRecord]] and provides some automatic attribute settings as `created_by` and `crated_at` if the underlying table contains these fields.
## Migrations
See Yii 2.0 guide for more details about migrations [http://www.yiiframework.com/doc-2.0/guide-db-migrations.html](http://www.yiiframework.com/doc-2.0/guide-db-migrations.html).
HumHub provides an enhanced Migration class [[humhub\components\Migration]] which provides the ability to rename class files. This is required because HumHub also stores some class names in database for Polymorphic relations.
#### Usage
- Create a module migration
`> php yii migrate/create example --migrationPath='@app/modules/polls/migrations'`
- Execute module migration
`> php yii migrate/up --migrationPath='@app/modules/polls/migrations'`
- Execute all migrations (including enabled modules)
`> php yii migrate/up --includeModuleMigrations=1`
#### Uninstall
There is a special migration file called 'uninstall.php' - which is executed after the module is uninstalled.
Use this drop created tables & columns.
Example file: *migrations/uninstall.php*
```php
<?php
use yii\db\Migration;
class uninstall extends Migration
{
public function up()
{
$this->dropTable('poll');
$this->dropTable('poll_answer');
$this->dropTable('poll_answer_user');
}
public function down()
{
echo "uninstall does not support migration down.\n";
return false;
}
}
```
## Data Integrity
The integrity checker is a command which validates and if necessary repairs the application database.
If you want to add own checking methods for your module to it, you can intercept the [[humhub\controllers\IntegrityController::EVENT_ON_RUN]] event.
Example callback implementation:
```php
public static function onIntegrityCheck($event)
{
$integrityController = $event->sender;
$integrityController->showTestHeadline("Polls Module - Answers (" . PollAnswer::find()->count() . " entries)");
foreach (PollAnswer::find()->joinWith('poll')->all() as $answer) {
if ($answer->poll === null) {
if ($integrityController->showFix("Deleting poll answer id " . $answer->id . " without existing poll!")) {
$answer->delete();
}
}
}
}
```

View File

@ -0,0 +1,12 @@
Change the behavior of core features
=================
This guide describes possible ways for modules to change the behavior of core features.
## Events
## Widgets
## Views
## Controller
## ActiveRecord
## Javascript
## Configuration

View File

@ -0,0 +1,247 @@
Module - Getting Started
=================
The following guide describes the basic module structure and extended module features as well as important considerations regarding your own custom module.
## Before starting
Before even starting the developement of a custom module, you first have to consider the following **module options**:
- [Can my module be enabled on profile and/or space level?](modules.md#container-module)
- Does my module produce [stream entries](stream.md) or other [content](content.md)?
- Does my module produce [global](content.md#global-content) content or views (not bound to a profile/space) ?
- Does my module provide any kind of sidebar [snippet](snippet.md)?
- Do I need to [change the default behaviour](module-change-behavior.md) of some core components?
- Do I need specific [permissions](permissions.md) for my module?
- Does my module create any [notifications](notifications.md) or [activities](activities.md)?
- Should [guest](permissions.md#guests-access) users have access to some of my module views and functions?
Furthermore you may have to consider the following **issues**:
- [Module settings and configuration](settings.md)
- [Append my module to a specific navigation](module-change-behavior.md)
- [Client side developement](javascript-index.md)
- [Asset Management](assets.md)
- [Data Integrity](models.md#data-integrity)
- [Migrations and Uninstallation and Compatibility](migration.md)
- [Testing](testing.md)
- [File handling](files.md)
- [Events](events.md)
- [Translation](i18n.md)
- [Live UI updates](live.md)
- [Submodules](#submodules)
- [Security](security.md)
- [Theming](embedded-themes.md)
## Basic Module Structure
Basically modules in HumHub are identical to [Yii2 modules](http://www.yiiframework.com/doc-2.0/guide-structure-modules.html).
A very basic module consists of the following elements:
```
controllers/ - contains controller classes
migrations/ - contains database migration files and uninstall script
models/ - contains model classes
views/ - contains the modules view files
widgets/ - contains widget classes
Module.php - the main module class which can contain enable/disable logic for contentcontainer etc.
config.php - base module configuration.
module.json - module metadata
```
### config.php
The `config.php` file enables automatic module loading and event configuration, without the need to manually modify the main application config, by returning an array including the following fields:
- **id** - Unqiue ID of the module (required)
- **class** - Namespaced classname of the module class (required)
- **namespace** - The namespace of your module (required)
- **events** - Array containing the modules event configuration (optional)
- **urlManagerRules** - Array of [URL Manager Rules](http://www.yiiframework.com/doc-2.0/yii-web-urlmanager.html#addRules()-detail) (optional)
- **modules** - Submodules (optional)
Example `config.php` file:
```php
<?php
use johndoe\example\Module;
use humhub\widgets\TopMenu;
return [
'id' => 'example',
'class' => 'johndoe\example\Module',
'namespace' => 'johndoe\example',
'events' => [
['class' => TopMenu::className(), 'event' => TopMenu::EVENT_INIT, 'callback' => ['johndoe\example\Module', 'onTopMenuInit']],
]
];
?>
```
> Note: Do not execute any code in the `config.php` since the result will be cached!
### Module.php
The `Module.php` file contains the actual module class which should either extend the [[humhub\components\Module]] or [[humhub\modules\content\components\ContentContainerModule]] class.
The [[humhub\components\Module|Module]] class provides some basic module functions used for installing/uninstalling and retrieving metadata, whereas the [[humhub\modules\content\components\ContentContainerModule]] class has to be extended in case your module requires to be enabled on space or profile level.
The Module class is responsible for:
**Handling the enabling and disabling of the module**
The modules `disable()` function is called if the module is disabled.
```php
class Module extends \humhub\components\Module
{
public function disable()
{
// Clear module related contentent etc...
foreach (MyContentModel::find()->all() as $model) {
$model->delete();
}
// Don't forget to call this!!
parent::disable();
}
}
```
>Note: The default implementation of `disable()` will clear some module data automatically as the module global and ContentContainer settings, profile/space module relations.
#### Handling the enabling and disabling of this module for a given space or profile
See the [Container Module]() section for more information.
#### Export Module Permissions
Module specific permissions are exported by means of the [[humhub\components\Module::getPermissions()]] function. See the [Permissions]() section for more information.
#### Export Module Notification
Modules can export Notificaions in order to make them configurable in the notificaiton settings.
See the [Notifications]() section for more information.
#### Module Assets and `$resourcesPath`
The [[humhub\components\Module::resourcesPath]] defines the modules resource directory, containing images, javascript files or other assets.
See the [Module Assets]() section for more information.
### module.json
This file holds basic metadata which is for example used by the markeplace.
Example `module.php` file:
```json
{
"id": "example",
"name": "My Example Module",
"description": "My testing module.",
"keywords": ["my", "cool", "module"],
"screenshots": ["assets/screen_1.jpg"],
"version": "1.0",
"humhub": {
"minVersion": "0.20"
}
}
```
- **id** - The module ID
- **name** - The modules name
- **description** - A short module description
- **keywords** - Array of significant keywords
- **screenshots** - Some screenshots for the marketplace
- **version** - Current module version
- **minVersion** - Defines the minimum HumHub core version this module version is compatible with.
## Extended Module Structure
The following structure contains some additional directories and files, which should be added for specific usecases or features.
```
activities - activity classes
assets/ - asset bundle classes
components/ - component and services classes
controllers/ - see above
live/ - live event classes
jobs/ - queue job classes
messages/ - contains the modules message files
migrations/ - see above
models/ - see above
modules/ - contains any submodules
notifications/ - notification classes
permissions/ - permission classes
resources/ - contains web assets as javascript files or stylesheets
tests/ - module tests
views/ - see above
widgets/ - see above
Events.php - is often used for static event handlers
Module.php - see above
config.php - see above
module.json - see above
```
>Note: the extended module structure and it's directory names is just a recommendation.
## Container Module
In case your module can be enabled on space or profile level your `Module` class has to extend from [[humhub\modules\content\components\ContentContainerModule]]. You should extend this class if your module provides space or profile specific views or content.
- The `getContentContainerTypes()` method defines for which ContentContainer type (space or profile) this module can be enabled.
- The `disableContentContainer()` method is called when this module is disabled for a given ContentContainer (Space or Profile).
- The `getContentContentContainerDescription()` method provides a general description of this module for the given ContentContainer.
The following example module can be enabled on space and profile level:
```php
class Module extends \humhub\modules\content\components\ContentContainerModule
{
// Defines for which content container type this module can be enabled
public function getContentContainerTypes()
{
// This content container can be assigned to Spaces and User
return [
Space::className(),
User::className(),
];
}
// Is called when the whole module is disabled
public function disable()
{
// Clear all Module data and call parent disable
[...]
parent::disable();
}
// Is called when the module is disabled on a specific container
public function disableContentContainer(ContentContainerActiveRecord $container)
{
parent::disableContentContainer($container);
//Here you can clear all data related to the given container
}
// Can be used to define a specific description text for different container types
public function getContentContainerDescription(ContentContainerActiveRecord $container)
{
if ($container instanceof Space) {
return Yii::t('MyModule.base', 'Description related to spaces.');
} elseif ($container instanceof User) {
return Yii::t('MyModule.base', 'Description related to user.');
}
}
}
```
> Note: If you're working with content or other persistent data, make sure to delete container related data when the module is disabled on a contentcontainer. This can be archieved by overwriting the [[humhub\modules\content\components\ContentContainerModule::disableContentContainer]] function.
## Creating a Module Template with Gii
(TBD)

View File

@ -0,0 +1,335 @@
Javascript API
=======
Since version 1.2, HumHub provides a module based Javascript API within the `humhub` namespace.
Instead of embeding inline script blocks into your view files, it's highly recommended to use the new module system for your modules frontend logic.
## Modules
### Module Asset
Module script files should reside within the `resources/js` folder of your humhub module and should ideally be appended at the bottom of your document. This can be achieved by using [Asset Bundles](http://www.yiiframework.com/doc-2.0/guide-structure-assets.html).
```php
namespace humhub\modules\example\assets;
use yii\web\AssetBundle;
class ExampleAsset extends AssetBundle
{
// You can also use View::POS_BEGIN to append your scripts to the beginning of the body element.
public $jsOptions = ['position' => \yii\web\View::POS_END];
public $sourcePath = '@example/resources';
public $js = [
'js/humhub.example.js'
];
}
```
> Note: Make sure to add your assets after the core scripts, which are added within the html head.
> Note: Your Asset Bundle should reside in the `assets` subdirectory of your module.
In your view you can register your Asset Bundle by calling
```php
\humhub\modules\example\assets\ExampleAsset::register($this);
```
Where `$this` is the view instance. More infos about the use of Asset Bundles are available in the [Yii Guide](http://www.yiiframework.com/doc-2.0/guide-structure-assets.html).
### Module Registration
Modules are added to the `humhub.modules` namespace by calling the `humhub.module` function.
```javascript
humhub.module('example', function(module, require, $) {
...
});
```
Example of a submodule:
```javascript
humhub.initModule('example.mySubmodule', function(module, require, $) {
...
}
```
The first argument of the `humhub.module` function defines the module id, which should be unique within your network. The second argument is the actual module function itself.
> Note: You should use an unique namespace for your custom modules as `myproject.mymodule` otherwise it may interfere with other modules.
Your module function will be called with the following arguments:
1. `module` - Your module instance, used for exporting module logic and accessing module specific utilities
2. `require` - Used for injecting other modules.
3. `$` - jQuery instance.
##### Module Exports
Module functions and attributes can only be accessed outside of the module if they are exported, either by directly appending them to the `module` object or by calling `module.export`.
```javascript
humhub.module('example', function(module, require, $) {
// private function
var private = function() { /* ... */ }
// direct export of public function
module.publicFunction = function() {/* ... */}
// another public function exported later
var publicTwo = function() { /* ... */}
// Exports multiple values
module.export({
publicTwo: publicTwo,
publicThree: function() {/** Test function **/}
});
});
```
##### Module Initialization
Your module's initialization logic can be implemented by exporting an `init` function. This function will automatically be called after the page is loaded.
By default this function is only called once after a full page load (or directly after the registration if it was loaded per ajax). If your module requires a reinitialization also after Pjax page loads, your module has to set the `initOnPjaxLoad` setting.
```javascript
module.initOnPjaxLoad = true;
var init = function($pjax) {
// Do some global initialization work, which needs to run in any case
if($pjax) {
// Runs only after a pjax page load
} else {
// Runs only after fresh page load
}
}
module.export({
init: init
});
```
##### Module Unload
For the purpose of cleaning up module related dom nodes etc. there is also an `unload` function, which is called before each Pjax page load. This function is mainly used to remove obsolete dom nodes in order to prevent memory leaks, remove obsolete dom listeners, or clear some module data.
```javascript
var unload = function($pjax) {
$('.moduleResidues').remove();
}
module.export({
unload: unload
});
```
##### Module Dependencies
Other modules can be injected into your module by using the `require` function.
```javascript
// Import of the core client module.
var client = require('client');
//Calling myFunction within another module
require('example').myFunction();
//Calling myFunction within another module (full path)
require('humhub.modules.example').myFunction();
//Also a valid call
require('modules.example').myFunction();
//Calling myFunction outside of a module
humhub.modules.example.myFunction();
```
> Note: You should only require modules at the beginning of your own module, if you are sure the required module is already registered.
If your module requires other modules, which are not part of the core you can ensure the order by means of the `$depends` attribute of your Asset Bundle:
```php
public $depends = [
'humhub\modules\anotherModule\assets\AnotherModuleAsset'
];
```
If you can't assure the module registration order for another module, but need to require the module, you can either require it within your module function or use the `lazy` flag of the require function.
The call of `require('anotherModule', true)` will return an empty namespace object, in case the module was not registered yet. The module logic will be available after the registration of the dependent module.
>Note: When using the `lazy` flag, you can't assure the required module will be initialized within your own module's `init` logic.
```javascript
humhub.initModule('example', function(module, require, $) {
// We can't ensure the initial logic of module2
var module2 = require('module2', true);
// at this point module2 might be empty
var myFunction = function() {
// myFunction should only be used outside of the init logic
module2.executeSomeFunction();
}
});
```
>Info: Since core modules are appended to the head section of your document, there shouldn't be any dependency problem.
### Module Configuration
If you need to transfer values as texts, settings or urls from your php backend to your frontend module, you can use the `module.config` array which is automatically available within your module as in the following example:
```javascript
humhub.initModule('example', function(module, require, $) {
var myAction = function() {
if(module.config.showMore) {
// Do something
}
};
});
```
In your view you can set the module configuration as follows
```php
// Single module
$this->registerJsConfig('example', ['showMore' => true]);
// Multiple modules
$this->registerJsConfig([
'example' => [
'showMore' => true
],
'anotherModule' => [
...
]
);
```
Setting configurations in javascript:
```javascript
//Set config values for multiple modules,
humhub.config.set({
'myModule': {
'myKey': 'value'
},
'moduleXY': {
...
}
});
//Set single value
humhub.config.set('myModule', {
'myKey': 'value'
});
//You can also call
humhub.config.set('myModule', 'myKey', 'value');
```
>Note: Since the configuration can easily be manipulated, you should not set values which can compromise the security of your application.
> TIP: Module setter are normally called within views or widgets to inject urls or translated text for user feedback or modals.
### Module Texts
Beside the configuration addition, the module instance does furthermore provide a `module.text` function for easily accessing texts of your configuration.
Example of an error text.
```php
//Configurate your text in your php view.
$this->registerJsConfig([
'example' => [
'showMore' => true,
'text' => [
'error.notallowed' => Yii::t('ExampleModule.views.example', 'You are not allowed to access example!');
]
]
);
```
Access your text within your module function as this
```javascript
module.text('error.notallowed');
// which is a short form of:
module.config['text']['error.notallowed'];
```
### Module Log
Your module is able to create module specific log entries by using the `module.log` object of your module instance.
The log object supports the following log level functions:
1. *trace* - For detailed trace output
2. *debug* - For debug output
3. *info* - Info messages
4. *success* - Used for success info logs
5. *warn* - Warnings
6. *error* - For error messages
7. *fatal* - Fatal errors
All log functions accept up to three arguments:
1. The actual message
2. Details about the message (or errors in case of warn/error/fatal)
3. A setStatus flag, which will trigger a global `humhub:modules:log:setStatus` event. This can be used to give user-feedback (status bar).
Instead of an actual message, you can also just provide a text key as the first argument.
The following calls are valid:
```javascript
// Log config text 'error.notallowed' and give user feedback.
module.log.error('error.notallowed', true);
// In the following example we received an error response by our humhub.modules.client. The response message will try to resolve a default
// message for the status of your response. Those default messages are configured in the core configuration texts.
module.log.error(response, true);
// The error.default text message is available through the configuration of the log module see humhub\widgets\JSConfig
module.log.error('error.default', new Error('xy'), true);
```
> Info: Your module logger will try resolving your message string to a module or global text.
> Note: The success log will by default trigger a status log event.
The trace level of your module can be configured by setting the `traceLevel` of your module configuration.
If your module does not define an own trace level the log modules's traceLevel configuration will be used.
> Info: In production mode the default log level is set to `INFO`, in dev mode its set to `DEBUG`.
> Note: If you change the `traceLevel` of a module at runtime, you'll have to call `module.log.update()`.
## Core Modules
### Config Module
Beside the `module.config` utility you can also use the global configuration as follows
```javascript
// Retrieves the whole config object of 'myModule'
var moduleConfig = require('config').get('myModule');
var myValue = config['myKey'];
//Single value getter with default value
var myValue = humhub.config.get('myModule', 'myKey', 'myDefaultValue');
```
With `humhub.config.is`, you are able to check if a value is true
```javascript
//Check if the configkey enabled is true, default false
if(humhub.config.is('myModule', 'enabled', 'false')) {
...
}
```

View File

@ -0,0 +1,182 @@
# Module Migration Guide to HumHub 0.20
This document briefly describes the module api changes in HumHub 0.20.
Since HumHub 0.20 is now based on Yii 2 you also need to migrate your modules to it.
See more information about Yii 2.0 here:
- [Yii: Upgrading from Version 1.1](http://www.yiiframework.com/doc-2.0/guide-intro-upgrade-from-v1.html)
- [Yii2 Migration Notes](dev-migrate-0.20-yii2.md)
## Migration
### General
- Namespace classes e.g. module\example or create own Namespace
- Migrate to Yii 2.0 (Controllers, Models, Views, Assets, ...)
- Migrate to HumHub Namespaced classes
- Raname e.g. ExampleModule.php && ExampleEvents.php to Module.php / Events.php
- Changed former autostart.php to config.php: [config.php](dev-module-index.md#configphp)
- Migrate database (see below)
### Database / Migrations
Also the existing migration script needs to use Namespaces now.
Because also class names of your module may stored in database (e.g. for Activities, Likes, Notification, ...)
It's neccessary to create a new migration derived from [[humhub\components\Migration]] which uses **renameClass** method class to fix these records.
Example Migration:
```php
<?php
use humhub\components\Migration;
use module\wiki\models\WikiPage;
use module\wiki\models\WikiPageRevision;
class m150705_081309_namespace extends Migration
{
public function up()
{
$this->renameClass('WikiPage', WikiPage::className());
$this->renameClass('WikiPageRevision', WikiPageRevision::className());
}
public function down()
{
echo "m150705_081309_namespace cannot be reverted.\n";
return false;
}
}
```
### Content & ContentAddon
getContentTitle is now divided into
- getContentTitle
- getContentPreview
### autostart.php
TBD
- Renamed to config.php
- Removed imports
- Return array
- Namespaces
### Urls
[[\humhub\modules\content\components\activerecords\ContentContainer::createUrl]] (Space/User) still provides the method createUrl to build URLs in container context (sguid/uguid).
Use [http://www.yiiframework.com/doc-2.0/yii-helpers-url.html](http://www.yiiframework.com/doc-2.0/yii-helpers-url.html) for other URLs.
### Activities
Please recreate Activities as described here: [[dev-module-activities.md]]
Since 0.20 there is an automatic "created" Activity for Content.
To migrate existing Activities to the new Scheme you need to create an migration.
Example Migration:
```php
// Rename Custom Activities
$this->update('activity', ['class' => 'exampleModule\activities\MyActivity'], ['class' => 'OldActivityName']);
// Rename own "Created" Activities to core
$this->update('activity', ['class' => 'humhub\modules\content\activities\ContentCreated', 'module' => 'content'], ['class' => 'PollCreated']);
```
### Assets
The asset/resources folder will not longer automatically published.
Find more details about assets here:
http://www.yiiframework.com/doc-2.0/guide-structure-assets.html
The default path for module resources (javascripts, images, css, ...) was changed from asset to resources. ('/modules/example/resources').
Also all HumHub module related files like Module Image or Screenshots should be located there.
You can change this path back to 'assets' by overwriting the 'resourcesPath' Attribute in your Module class.
e.g.
```php
class Module extends \humhub\components\Module
{
public $resourcesPath = 'assets';
```
### Module Configuration
The URL handling to configure your module in **Administration -> Module** has changed.
The method "getConfigUrl" in Module class is not longer used.
Set configRoute attribute instead.
e.g.
```php
class Module extends \humhub\components\Module
{
public $configRoute = '/example/admin/config';
```
## (Incomplete) List of changed Helpers/Widgets:
#### EnrichText
```php
// New
echo humhub\widgets\RichText::widget(['text' => $text]);
// Old
echo HHtml::enrichTest($text);
```
#### TimeAgo
```php
// New
echo \humhub\widgets\TimeAgo::widget(['timestamp' => $time]);
// Old
echo HHtml::timeAgo($time);
```
#### PostLink
```php
// New
echo Html::a($label, $url, ['data-method'=>'POST']);
// Old:
echo HHtml::postLink(...);
```
#### AjaxButton/Submit/...
```php
echo \humhub\widgets\AjaxButton::widget([
'label' => "Save",
'ajaxOptions' => [
'type' => 'POST',
'beforeSend' => new yii\web\JsExpression('function(){ setModalLoader(); }'),
'success' => new yii\web\JsExpression('function(html){ $("#globalModal").html(html); }'),
'url' => $space->createUrl('/space/admin/crop-image'),
],
'htmlOptions' => [
'class' => 'btn btn-primary'
]
]);
```
#### Yii::app()->input->stripClean
Stripclean is not longer available. use Html::encode() user input on output _and_ create validators.

View File

@ -0,0 +1,41 @@
[Back to 0.20 Migration](modules-migrate-0.20.md)
# Yii2 Migration Notes
See Yii Migration Guide: [http://www.yiiframework.com/doc-2.0/guide-intro-upgrade-from-v1.html](http://www.yiiframework.com/doc-2.0/guide-intro-upgrade-from-v1.html)
Notes:
- Use Namespaces!
- Yii::app() -> Yii::$app
- Use [] instead of array() - Optional
- Model: Validator
- Use array for multiple attributes
- Validator changes Numeric->Integer ...
- String validator doesn't allow Integer Types (cast!)
- Scenarios now in separate methods secenarios()
- User::model()->findByPk($idy); -> User::findOne(['id'=>$id);
- Check beforeSave/afterSave when overwriting they may have parameters
- Better use $insert when available instead of $this->isNewRecord
- Make tableName method static
- Views:
- ClientScript removed e.g. Yii::app()->clientScript->registerScriptFile
- New Widget calls WidgetClass::widget([options]) & echo it!
- Controllers
- Always return render action (also Widgets)
- camel case actions e.g. actionEditItem new Url: edit-item
- Easier: JSON Output
Yii::$app->response->format = 'json'; return $json;
- createUrl removed -> Url::to()
- Behaviors
- $this->getOwner() replaced by $this->owner
- Html (CHtml)
- reduced (e.g. no AjaxButton - use: \humhub\widgets\AjaxButton instead
- Html::link -> confirm changed to data-confirm
-

View File

@ -1,48 +1,40 @@
Overview
========
The main power of the HumHub platform lies in its flexibility and extensibility through modules and configuration of runtime behaviour.
HumHub is written mostly in PHP and is based on the [Yii Framework](http://www.yiiframework.com/). Other languages used throughout the platform are *JavaScript*, *HTML*, *SQL* and *CSS*.
HumHub provides a powerful modular platform based on the [Yii2 Framework](http://www.yiiframework.com).
The modular nature of the HumHub platform allows you to add new features or change existing core features by means of
custom modules.
HumHub uses a [Model-View-Controller (MVC)](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller) based software architecture and utilizes technologies such as [Yii2](http://www.yiiframework.com/), [jQuery](https://jquery.com/), [Bootstrap](http://getbootstrap.com/) and [Less](http://lesscss.org/), to name a few.
Other languages used throughout the platform, besides PHP, are JavaScript, HTML, SQL and CSS/Less.
HumHub is based on the Model-View-Controller (MVC) pattern and uses frontend technologies such as [jQuery](https://jquery.com/), [Bootstrap](http://getbootstrap.com/) and [Less](http://lesscss.org/).
In this guide, you will find all the necessary information to customize your HumHub installation and implement your own modules.
As HumHub is based on the [Yii 2.0 PHP Framework](http://www.yiiframework.com/) make sure you're also familiar with the basic concepts this framework:
- [The Definitive Guide to Yii 2.0](http://www.yiiframework.com/doc-2.0/guide-index.html)
## HumHub Core
![Application Layers](images/appLayer.svg)
> Note: Since HumHub v1.2 the minimum PHP version is 5.6
The HumHub core consists of a set of core components, modules, widgets, helpers and views.
HumHub extends several Yii base components such as:
As HumHub is based on the [Yii 2.0 PHP Framework](http://www.yiiframework.com/) make sure you're also familiar with the concepts of this framework in order to beeing able to write own modules or extend the core platform.
- [[humhub\components\ActiveRecord|ActiveRecord]]
- [[humhub\components\Application|Application]]
- [[humhub\components\Controller|Controller]]
- [[humhub\components\Migration|Migration]]
- [[humhub\components\Module|Module]]
- [[humhub\components\ModuleManager|ModuleManager]]
- [[humhub\components\Request|Request]]
- [[humhub\components\Theme|Theme]]
- [[humhub\components\User|User]]
- [[humhub\components\View|View]]
- [[humhub\components\Widget|Widget]]
- and more...
Here are some recommendet resources for learning Yii:
- [The Definitive Guide to Yii 2.0](http://www.yiiframework.com/doc-2.0/guide-index.html)
- [Yii 2.0 Community Cookbook](https://yii2-cookbook.readthedocs.io/)
The HumHub core platform consists of several modules as well as extended Yii components:
**Core Components:**
- [[humhub\components\ActiveRecord]]
- [[humhub\components\Application]]
- [[humhub\components\console\Application]]
- [[humhub\components\AssetManager]] -
- [[humhub\components\Controller]]
- [[humhub\components\Migration]]
- [[humhub\components\Module]]
- [[humhub\components\ModuleManager]]
- [[humhub\components\Request]]
- [[humhub\components\Response]]
- [[humhub\components\SettingsManager]]
- [[humhub\components\Theme]]
- [[humhub\components\SocialActivity]]
- [[humhub\components\View]]
- [[humhub\components\Widget]]
- **humhub\components\i18n**
- **humhub\components\mail**
- **humhub\components\queue**
- **humhub\components\rendering**
- **humhub\components\validators**
**Core Modules:**
and consists of the following core modules:
- **activity:** User/Space activities
- **admin:** Responsible for admin/configuration related issues
@ -51,14 +43,29 @@ The HumHub core platform consists of several modules as well as extended Yii com
- **dashboard:** Dashboard related functionality
- **directory:** Directory related functionality
- **file:** Basic file module for accessing the filesystem
- **friendship:** Friendship system functionality
- **friendship:** User friendship module
- **installer:** HumHub installer module
- **like:** Content addon for likes
- **live:** Live frontend update functionality
- **notification:** User notifications (e.g. e-mail, web)
- **live:** Used for frontend live updates
- **notification:** User Notifications
- **post:** Simple user-post related functionality
- **search:** Luceene Search Module
- **space:** Space related functionality
- **stream:** Content stream related functionality
- **tour:** HumHub user-guide tour
- **user:** User and authentication
- **stream:** Content streams and walls
- **tour:** HumHub user-guide
- **user:** Basic user module
### Application structure
```
assets/ - contains published asset files
protected/ - protected files as sources, modules, configuration etc.
protected/config - dynamic and user configuration
protected/humhub - humhub core directory
protected/modules - default directory for non core modules
protected/runtime - runtime files as cache, search index, logs etc.
protected/vendor - third party libraries loaded by composer
static/ - static asset files as production assets core javascript/less files etc.
themes/ - contains standalone themes (not bundled within a module)
uploads/ - uploaded files profile images etc.
```

View File

@ -232,4 +232,7 @@ return [
]
];
```
```
## Guest Access
(TBD)

View File

@ -0,0 +1,4 @@
Security
=================
(TBD)

View File

@ -0,0 +1,75 @@
Settings Manager
================
The SettingsManager allows you to easily store key/value based configuration settings
based on module components and also optionally bound to a contentcontainer (e.g. users or spaces).
If you need to categorize key names, use this syntax: category.subcategory.camelCaseKeyName
The SettingsManager component is automatically added all to humhub\components\Module classes.
Module settings
---------------
Get desired module / application instance:
```php
$module = Yii::$app;
// or
$module = Yii::$app->getModule('polls');
// or
$module = $controller->module;
```
Create or update existing setting in settings manager:
```php
$module->settings->set('key', $value);
```
Get value of setting manager:
```php
$value = $module->settings->get('key');
```
Delete setting:
```php
$module->settings->delete('key');
// or
$module->settings->set('key', null);
```
ContentContainer related settings
---------------------------------
If you want to store settings related to an user or space - use the ContentContainerSettingsManager:
```php
$module->settings->contentContainer($user)->get('key');
$module->settings->contentContainer($user)->set('key', $value);
$module->settings->contentContainer($user)->delete('key');
```
Shortcuts for currently logged in user settings:
```php
$module->settings->user()->get('key');
$module->settings->user()->set('key', $value);
$module->settings->user()->delete('key');
```
Shortcuts for current space settings:
Note: This is only available if current controller is instance of ContentContainerController.
```php
$module->settings->space()->get('key');
$module->settings->space()->set('key', $value);
$module->settings->space()->delete('key');
```

View File

@ -0,0 +1,6 @@
Snippets
=================
Snippets are self contained panels which can be added to the sidebar of for exaple the space or dashboard layout.
(TBD)

View File

@ -1,18 +1,136 @@
# Streams / Walls
Content Streams
=================
Streams are used to asynchronously load batches of content entries which can be filtered or sorted.
The stream concept is used for example in _space and profile walls_, the _dashboard_ and
_activity stream_.
TBD
Custom modules can use own streams for example to filter content by a specific type, or other custom
filters.
- Define Streaming/Wall
### Stream Channel
You can also implement Creanown Stream/Wall output for your module content only.
The `stream_channel` attribute of a [[humhub\modules\content\models\Content]] entry defines the relation of this content to
a specific type of stream. The `default` stream channel for example is used by _space/profile_ and _dashboard_
streams and the `activity` stream channel is exclusively used in activity streams.
Example Implementations:
The stream channel of your content type can be overwritten by setting the [[humhub\modules\content\components\ContentActiveRecord::streamChannel|ContentActiveRecord::streamChannel]] attribute.
- Tasks
- Polls
You can consider the following stream channel options for your own [[humhub\modules\content\components\ContentActiveRecord|ContentActiveRecord]]:
Of course your modules Content implementation needs to provides a WallEntry widget. See Content Section for more details.
- `default` stream channel will include your content to default _space/profile walls_ and the _dashboard_. You are still able to create a custom stream view which filters content by type.
- `null` will exclude the content from the default streams
- Use a custom stream channel if you exclusively want your content to be included in your own custom stream (similar to activity concept).
> Note: A custom stream channel should be unique, so choose a meaningful name preferably with module prefix.
### WallEntry Widget
A [[humhub\modules\content\widgets\WallEntry|WallEntry widget]] is responsible for rendering the individual stream entries
of a stream and is defined by [[humhub\modules\content\components\ContentActiveRecord::wallEntryClass|ContentActiveRecord::wallEntryClass]].
The following example shows a very basic WallEntry widget implementation.
> Note: By default your WallEntry view only have to render the actual content, the default WallEntry layout is available in `@humhub/modules/content/widgets/views/wallEntry.php`
```php
class WallEntry extends \humhub\modules\content\widgets\WallEntry
{
public function run()
{
return $this->render('wallEntry', [
'model' => $this->contentObject
]);
}
}
```
wallEntry.php:
```php
<div>
<?= $model->title ?>
<?= $model->myContent ?>
...
</div>
```
The WallEntry widget will be provided with a [[humhub\modules\content\widgets\WallEntry::contentObject|contentObject]] which holds the
[humhub\modules\content\components\ContentActiveRecord|ContentActiveRecord]] model to be rendered.
Your [[humhub\modules\content\widgets\WallEntry|WallEntry]] class can also set the following attributes:
- [[humhub\modules\content\widgets\WallEntry::editRoute|editRoute]] defines an edit route to your edit action which will be used to render an edit link (see WallEntryControls section)
- [[humhub\modules\content\widgets\WallEntry::editMode|editMode]] defines the way the edit action is triggered (see WallEntryControls section)
- [[humhub\modules\content\widgets\WallEntry::wallEntryLayout|wallEntryLayout]] defines the layout used to embed the result of `render()`, by default you only have to care about rendering the content section of your WallEntry
#### WallEntryControls
The default WallEntry layout contains a context menu with content actions like `edit`, `delete`, `archive` etc.
This menu can be manipulated by overwriting the [[humhub\modules\content\widgets\WallEntry::getContextMenu()|getContextMenu()]] function and
or use the [[humhub\modules\content\widgets\WallEntry::controlsOptions|controlsOptions]] property as in the following example.
By setting the [[humhub\modules\content\widgets\WallEntry::editRoute|editRoute]] we automatically add an edit link to our WallEntryControls in
case the current user is allowed to edit the content. The type of the edit action is defined by the [[humhub\modules\content\widgets\WallEntry::editMode|editMode]].
There are the following edit modes available:
- `EDIT_MODE_MODAL` the response of `editRoute` will be loaded into a modal.
- `EDIT_MODE_INLINE` the response of `editRoute` will be embeded into the WallEntry content.
- `EDIT_MODE_NEW_WINDOW` the page response of `editRoute` will be fully loaded.
```php
class WallEntry extends \humhub\modules\content\widgets\WallEntry
{
public $editRoute = "/my-module/entry/edit";
public $editMode = self::EDIT_MODE_MODAL;
// Will prevent the default DeleteLink and always add a MySpecialLink
$this->controlsOptions = [
'prevent' => [\humhub\modules\content\widgets\DeleteLink::class],
'add' => [MySpecialLink::class]
];
//...
public function getContextMenu()
{
$result = parent::getContextMenu();
// Only add a CloseLink if the user is allowed to edit the content.
if($this->contentObject->content->canEdit()) {
$this->addControl($result, [CloseLink::class, ['model' => $this->contentObject], ['sortOrder' => 200]]);
}
return $result;
]
}
```
CloseLink example:
```php
class CloseLink extends humhub\modules\content\widgets\WallEntryControlLink
{
public $model;
public function init()
{
if($this->model->closed) {
$this->label = Yii::t('MyModule.base', 'Reopen');
$this->icon = 'fa-check';
} else {
$this->label = Yii::t('MyModule.base', 'Close');
$this->icon = 'fa-times';
}
$this->options = [
// set some further html options
];
parent::init();
}
}
```
## Create own Module Content Stream
@ -23,24 +141,14 @@ Derived from [[humhub\modules\content\components\actions\ContentContainerStream]
Example:
```php
<?php
namespace humhub\modules\polls\components;
use humhub\modules\content\components\actions\ContentContainerStream;
use humhub\modules\polls\models\Poll;
class StreamAction extends ContentContainerStream
class StreamAction extends humhub\modules\content\components\actions\ContentContainerStream
{
public function setupFilters()
{
// Limit output to specific content type
$this->activeQuery->andWhere(['content.object_model' => Poll::className()]);
}
}
```
Specify Action in Controller

View File

@ -1,6 +1,17 @@
Testing (since v1.2)
====================
## Testing basics
Testing in Humhub/Yii extends the paradigm of unit testing. I.e. testing models and controllers is complemented by functional and acceptance tests. Acceptance tests cover scenarios from a user's perspective: Opening the browser, accessing the site, click links and buttons etc. This behaviour can be simulated. Therefore a webserver as well as an automated browser instance are necessary (see below).
Functional tests are similar to acceptance tests but run without a running webserver.
Codeception allows integrated testing with acceptance, functional and unit tests.
*ATTENTION: Some of the test libraries are developed for use with PHP 7 only*
Details: [Codeception](http://codeception.com/docs/01-Introduction)
## Test Environment Setup
- Install codeception ([http://codeception.com/install](http://codeception.com/install))
@ -13,7 +24,7 @@ composer global require "codeception/codeception=2.0.*" "codeception/specify=*"
- Create test Database:
```
CREATE DATABASE `humhub_test` CHARACTER SET utf8 COLLATE utf8_general_ci;
CREATE DATABASE `humhub_test` CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
```
- Configure database access:
@ -21,7 +32,7 @@ CREATE DATABASE `humhub_test` CHARACTER SET utf8 COLLATE utf8_general_ci;
Configure the database connection for your test environment in `@humhub/tests/config/common.php`:
```
'components' => [
'db' => [
'dsn' => 'mysql:host=localhost;dbname=humhub_test',
@ -30,36 +41,33 @@ Configure the database connection for your test environment in `@humhub/tests/co
'charset' => 'utf8',
],
]
```
- Run Database Migrations:
```cd protected/humhub/tests/codeception/bin```
`cd protected/humhub/tests/codeception/bin`
```php yii migrate/up --includeModuleMigrations=1 --interactive=0```
`php yii migrate/up --includeModuleMigrations=1 --interactive=0`
```php yii installer/auto```
`php yii installer/auto`
>Note: You'll have to run the migrations for your test environment manually in order to keep your test environment up to date.
- Install test environment:
```cd protected/humhub/tests/codeception/bin```
```php yii migrate/up --includeModuleMigrations=1 --interactive=0```
```php yii installer/auto```
`php yii installer/auto`
- Set `HUMHUB_PATH` system variable
The `HUMHUB_PATH` is used by your test environment to determine the humhub root path.
This is only required for non core module tests and can also be set in your modules test configuration `/tests/config/test.php`:
```
return [
'humhub_root' => '/path/to/my/humhub/root',
];
```
## Test configuration
@ -74,11 +82,11 @@ The following configuration files can be used to overwrite the test configuratio
The configurations for a suite will be merged in the following order:
- @humhub/protected/humhub/tests/config/functional.php
- @myModule/tests/config/common.php
- @myModule/tests/config/functional.php
- @myModule/tests/config/env/myenv/common.php (if exists)
- @myModule/tests/config/env/myenv/functional.php (if exists)
- `@humhub/protected/humhub/tests/config/functional.php`
- `@myModule/tests/config/common.php`
- `@myModule/tests/config/functional.php`
- `@myModule/tests/config/env/myenv/common.php (if exists)`
- `@myModule/tests/config/env/myenv/functional.php (if exists)`
### Environments
@ -106,17 +114,17 @@ humhub_root settings you want to use for this test run.
### Run all core tests:
´´´
```
cd protected/humhub/tests/
codecept run
´´´
```
### Run core module test
´´´
```
cd myModule/tests
codecept run unit
´´´
```
### Run non core module tests
@ -147,18 +155,20 @@ return [
### Run single test
```
codecept run codeception/acceptance/TestCest:testFunction
```
`codecept run codeception/acceptance/TestCest:testFunction`
### Run acceptance tests
Phantom.js and Selenium are needed as servers to run acceptance tests on your system. You can simply run codeception but selenium or phantomjs must be running.
Hint: If your already installed webserver is listening on port 8080 you do not need to start the test server, because Humhub tests are run on port 8080. However if your `DocumentRoot` directory is not configured to directly open humhub via `localhost` you have to do some adjustments in the `codeception.yml` file of our `test` folder (`test-entry-url`) and the `acceptance.suite.yml` file. Alternatively start the test server as described below (in humhub root directory).
#### with phantomjs
- Run phantomjs server (is installed with composer update)
```cd protected/vendor/bin```
`cd protected/vendor/bin`
```phantomjs --webdriver=44444```
`phantomjs --webdriver=44444`
#### with chrome driver (selenium)
@ -172,11 +182,10 @@ java -Dwebdriver.chrome.driver=chromedriver.exe -jar selenium-server-standalone-
Start test server:
```cd /myhumHubInstallation```
`cd /myhumHubInstallation`
```php -S localhost:8080```
`php -S localhost:8080`
run with chrome environment:
```codecept run acceptance --env chrome```
`codecept run acceptance --env chrome`

View File

@ -1,47 +1,8 @@
Custom Assets
=============
Structure
---------
Put your custom assets (e.g. images, fonts or javascripts) directly in the theme base directory.
Example:
- /themes/mytheme/img (Images)
- /themes/mytheme/js (Javascript files)
- /themes/mytheme/css (CSS Stylesheets)
- /themes/mytheme/font (Fonts)
TBD
Usage
------
You can access the assets using the [[humhub/components/theme]] component.
Example:
```
<a href="<?= Url::to(['/']); ?>"><img src="<?= $this->theme->getBaseUrl() . '/img/mylogo.png'; ?>" alt="My logo"></a>
```
Javascript and Stylesheets
---------------------------
In order to load additional **CSS** or **JavaScript** files in your theme, add them to `/themes/mytheme/views/layouts/head.php`
e.g.
```
<link href="<?= $this->theme->getBaseUrl() . '/font/nexa/typography.css'; ?>" rel="stylesheet">
```
Overwrite default images
------------------------
You can also overwrite default images (stored in /static/img/) by placing a custom image with the same file name in your theme image directory.
If you want to replace the default user image as example, you need to create a file called **default_user.jpg** in your `/theme/mytheme/img` directory.
In order to load additional **CSS** or **JavaScript** files in your theme, add them to `/themes/mytheme/views/layouts/head.php`

View File

@ -27,7 +27,7 @@ If you are using the command line tool [lessc](http://lesscss.org/), you can bui
lessc -x themes/Example/less/build.less themes/Example/css/theme.css
```
or respectively by using [grunt](../developer/core-build.md):
or respectively by using [grunt](../developer/build.md):
```
grunt build-theme --name=Example

View File

@ -11,7 +11,7 @@ All changes or additions will be automatically applied to your theme.
## View Files
As mentioned in the [View Files](view.md) section, you may need to manually adjust overwritten view files if there are any changes made in the new **HumHub** version.
As mentioned in the [View Files](views.md) section, you may need to manually adjust overwritten view files if there are any changes made in the new **HumHub** version.
### Identifing changes using Git command

View File

@ -1,10 +1,8 @@
Tutorial
========
Foreword
--------
This quick tutorial shows you all necessary steps to create a custom **HumHub** theme.
- Step 1: Create a theme folder ([Theme Folder Structure](structure.md))
@ -14,23 +12,21 @@ This quick tutorial shows you all necessary steps to create a custom **HumHub**
Step 1: Create an own theme folder
---------------------------------
- Go to the HumHub installation directory
- Switch to the directory `themes`
- Copy the folder `HumHub` and rename it to `Example`
- Enable the new `Example` theme under `Administration -> Settings -> Appearance`
Step 2: Adjust colors and build CSS
-----------------------------------
### Installing prerequisites
** Install NodeJS **
**Install NodeJS**
See: https://nodejs.org/en/download/
** Install LESS **
**Install LESS**
Open the command console and execute:
@ -39,7 +35,6 @@ npm -g install less
```
### Modify theme colors
Add modifed color variables to the file `/themes/Example/less/variables.less`.
```
@ -52,7 +47,6 @@ Add modifed color variables to the file `/themes/Example/less/variables.less`.
```
### Compile LESS file
Open the command console and change to the themes `less` directory
```
@ -66,25 +60,21 @@ lessc build.less ../css/theme.css
```
### Test the result
- Flush your browsers cache
- Flush the HumHub cache (if enabled): `Administration -> Settings -> Advanced -> Cache -> Flush`
- Fully reload the page
![Example](images/color-example.png)
Step 3: Modify login template
------------------------------
In this step we're adding some text to the login template.
### Create a themed view file
Copy the view file `humhub/modules/user/views/auth/login.php` to `Example/views/user/auth/login.php`
### Modify the view file
Add some additional text below the application name.
```php
@ -100,11 +90,9 @@ Add some additional text below the application name.
```
Text Example:
![Example Text](images/modify-template.png)
### Result
![Result](images/modify-template-result.png)

View File

@ -96,7 +96,9 @@ class ActionColumn extends Column
*/
protected function handleUrl($url, $model)
{
$url[$this->modelIdAttribute] = $model->getAttribute($this->modelIdAttribute);
if (!isset($url[$this->modelIdAttribute])) {
$url[$this->modelIdAttribute] = $model->getAttribute($this->modelIdAttribute);
}
return \yii\helpers\Url::to($url);
}

View File

@ -2,16 +2,16 @@
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2017 HumHub GmbH & Co. KG
* @copyright Copyright (c) 2018 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\libs;
use humhub\modules\space\models\Space;
use Yii;
use yii\base\Object;
use yii\base\Exception;
use humhub\modules\space\models\Space;
/**
* BasePermission
@ -92,7 +92,7 @@ class BasePermission extends Object
*/
public function getId()
{
if ($this->id != "") {
if ($this->id != '') {
return $this->id;
}
@ -145,7 +145,7 @@ class BasePermission extends Object
if ($configuredState !== null) {
return $configuredState;
} else if ($this->defaultState == self::STATE_ALLOW) {
} elseif ($this->defaultState == self::STATE_ALLOW) {
return self::STATE_ALLOW;
} else {
return (int) (in_array($groupId, $this->defaultAllowedGroups));
@ -163,8 +163,9 @@ class BasePermission extends Object
*/
protected function getConfiguredState($groupId)
{
if (isset(Yii::$app->params['defaultPermissions'][self::className()]) && isset(Yii::$app->params['defaultPermissions'][self::className()][$groupId])) {
return Yii::$app->params['defaultPermissions'][self::className()][$groupId];
if (isset(Yii::$app->params['defaultPermissions'][self::className()]) &&
isset(Yii::$app->params['defaultPermissions'][self::className()][$groupId])) {
return Yii::$app->params['defaultPermissions'][self::className()][$groupId];
}
return null;

View File

@ -9,6 +9,7 @@
namespace humhub\libs;
use Yii;
use yii\base\Object;
use yii\helpers\ArrayHelper;
/**
@ -16,7 +17,7 @@ use yii\helpers\ArrayHelper;
*
* @author luke
*/
class DynamicConfig extends \yii\base\Object
class DynamicConfig extends Object
{
/**
@ -26,7 +27,7 @@ class DynamicConfig extends \yii\base\Object
*/
public static function merge($new)
{
$config = \yii\helpers\ArrayHelper::merge(self::load(), $new);
$config = ArrayHelper::merge(self::load(), $new);
self::save($config);
}
@ -49,7 +50,7 @@ class DynamicConfig extends \yii\base\Object
$config = eval($configContent);
if (!is_array($config))
return array();
return [];
return $config;
}
@ -61,15 +62,14 @@ class DynamicConfig extends \yii\base\Object
*/
public static function save($config)
{
$content = "<" . "?php return ";
$content = '<' . '?php return ';
$content .= var_export($config, true);
$content .= "; ?" . ">";
$content .= '; ?' . '>';
$configFile = self::getConfigFilePath();
file_put_contents($configFile, $content);
if (function_exists('opcache_invalidate')) {
opcache_reset();
opcache_invalidate($configFile);
}
@ -91,14 +91,14 @@ class DynamicConfig extends \yii\base\Object
// Add Default language
$defaultLanguage = Yii::$app->settings->get('defaultLanguage');
if ($defaultLanguage !== null && $defaultLanguage != "") {
if ($defaultLanguage !== null && $defaultLanguage != '') {
$config['language'] = Yii::$app->settings->get('defaultLanguage');
} else {
$config['language'] = Yii::$app->language;
}
$timeZone = Yii::$app->settings->get('timeZone');
if ($timeZone != "") {
if ($timeZone != '') {
$config['timeZone'] = $timeZone;
$config['components']['formatter']['defaultTimeZone'] = $timeZone;
$config['components']['formatterApp']['defaultTimeZone'] = $timeZone;
@ -126,14 +126,14 @@ class DynamicConfig extends \yii\base\Object
}
// Add User settings
$config['components']['user'] = array();
$config['components']['user'] = [];
if (Yii::$app->getModule('user')->settings->get('auth.defaultUserIdleTimeoutSec')) {
$config['components']['user']['authTimeout'] = Yii::$app->getModule('user')->settings->get('auth.defaultUserIdleTimeoutSec');
}
// Install Mail Component
$mail = [];
$mail['transport'] = array();
$mail['transport'] = [];
if (Yii::$app->settings->get('mailer.transportType') == 'smtp') {
$mail['transport']['class'] = 'Swift_SmtpTransport';

View File

@ -2,12 +2,13 @@
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2017 HumHub GmbH & Co. KG
* @copyright Copyright (c) 2018 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\libs;
use humhub\modules\user\authclient\ZendLdapClient;
use Yii;
/**
@ -37,54 +38,54 @@ class SelfTest
* ['state'] = OK, WARNING, ERROR
* ['hint']
*/
$checks = array();
$checks = [];
// Checks PHP Version
$title = 'PHP - Version - ' . PHP_VERSION;
if (version_compare(PHP_VERSION, '5.6', '>=')) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Minimum 5.6'
);
];
}
// Checks GD Extension
$title = 'PHP - GD Extension';
if (function_exists('gd_info')) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Install GD Extension'
);
];
}
// Checks INTL Extension
$title = 'PHP - INTL Extension';
if (function_exists('collator_create')) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Install INTL Extension'
);
];
}
$icuVersion = (defined('INTL_ICU_VERSION')) ? INTL_ICU_VERSION : 0;
@ -93,16 +94,16 @@ class SelfTest
$title = 'PHP - INTL Extension - ICU Version (' . $icuVersion . ')';
if (version_compare($icuVersion, $icuMinVersion, '>=')) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'WARNING',
'hint' => 'ICU Data ' . $icuMinVersion . ' or higher is required'
);
];
}
$icuDataVersion = (defined('INTL_ICU_DATA_VERSION')) ? INTL_ICU_DATA_VERSION : 0;
$icuMinDataVersion = '4.8.1';
@ -110,209 +111,191 @@ class SelfTest
$title = 'PHP - INTL Extension - ICU Data Version (' . $icuDataVersion . ')';
if (version_compare($icuDataVersion, $icuMinDataVersion, '>=')) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'WARNING',
'hint' => 'ICU Data ' . $icuMinDataVersion . ' or higher is required'
);
];
}
// Checks EXIF Extension
$title = 'PHP - EXIF Extension';
if (function_exists('exif_read_data')) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Install EXIF Extension'
);
];
}
// Check FileInfo Extension
$title = 'PHP - FileInfo Extension';
if (extension_loaded('fileinfo')) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Install FileInfo Extension'
);
];
}
// Checks Multibyte Extension
$title = 'PHP - Multibyte String Functions';
if (function_exists('mb_substr')) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Install PHP Multibyte Extension'
);
];
}
// Checks iconv Extension
$title = 'PHP - iconv Extension';
if (function_exists('iconv_strlen')) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Install PHP iconv Extension'
);
];
}
// Checks cURL Extension
$title = 'PHP - cURL Extension';
if (function_exists('curl_version')) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Install Curl Extension'
);
];
}
// Checks ZIP Extension
$title = 'PHP - ZIP Extension';
if (class_exists('ZipArchive')) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Install PHP ZIP Extension'
);
];
}
// Checks LDAP Extension
$title = 'LDAP Support';
if (\humhub\modules\user\authclient\ZendLdapClient::isLdapAvailable()) {
$checks[] = array(
if (ZendLdapClient::isLdapAvailable()) {
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'WARNING',
'hint' => 'Optional - Install PHP LDAP Extension and Zend LDAP Composer Package'
);
];
}
// Checks APC(u) Extension
$title = 'PHP - APC(u) Support';
if (function_exists('apc_add') || function_exists('apcu_add')) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'WARNING',
'hint' => 'Optional - Install APCu Extension for APC Caching'
);
];
}
// Checks SQLite3 Extension
$title = 'PHP - SQLite3 Support';
if (class_exists('SQLite3')) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'WARNING',
'hint' => 'Optional - Install SQLite3 Extension for DB Caching'
);
];
}
// Checks PDO MySQL Extension
$title = 'PHP - PDO MySQL Extension';
if (extension_loaded('pdo_mysql')) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Install PDO MySQL Extension'
);
];
}
// Checks Writeable Config
/*
$title = 'Permissions - Config';
$configFile = dirname(Yii::$app->params['dynamicConfigFile']);
if (is_writeable($configFile)) {
$checks[] = array(
'title' => Yii::t('base', $title),
'state' => 'OK'
);
} else {
$checks[] = array(
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Make ' . $configFile . " writable for the webserver/php!"
);
}
*/
// Check Runtime Directory
$title = 'Permissions - Runtime';
$path = Yii::getAlias('@runtime');
if (is_writeable($path)) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Make ' . $path . " writable for the webserver/php!"
);
'hint' => 'Make ' . $path . " writable for the Webserver/PHP!"
];
}
// Check Assets Directory
@ -320,16 +303,16 @@ class SelfTest
$path = Yii::getAlias('@webroot/assets');
if (is_writeable($path)) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Make ' . $path . " writable for the webserver/php!"
);
'hint' => 'Make ' . $path . " writable for the Webserver/PHP!"
];
}
// Check Uploads Directory
@ -337,16 +320,16 @@ class SelfTest
$path = Yii::getAlias('@webroot/uploads');
if (is_writeable($path)) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Make ' . $path . " writable for the webserver/php!"
);
'hint' => 'Make ' . $path . " writable for the Webserver/PHP!"
];
}
// Check Custom Modules Directory
@ -354,16 +337,16 @@ class SelfTest
$path = Yii::getAlias(Yii::$app->params['moduleMarketplacePath']);
if (is_writeable($path)) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Make ' . $path . " writable for the webserver/php!"
);
'hint' => 'Make ' . $path . " writable for the Webserver/PHP!"
];
}
// Check Custom Modules Directory
$title = 'Permissions - Dynamic Config';
@ -374,16 +357,16 @@ class SelfTest
}
if (is_writeable($path)) {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'OK'
);
];
} else {
$checks[] = array(
$checks[] = [
'title' => Yii::t('base', $title),
'state' => 'ERROR',
'hint' => 'Make ' . $path . " writable for the webserver/php!"
);
'hint' => 'Make ' . $path . " writable for the Webserver/PHP!"
];
}
return $checks;

View File

@ -58,6 +58,8 @@ return [
'Show less' => '',
'Show more' => '',
'Some files could not be uploaded:' => '',
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'The date has to be in the past.' => '',
'The file has been deleted.' => '',
'The requested resource could not be found.' => '',

View File

@ -44,6 +44,8 @@ return [
'Select Me' => '',
'Show less' => '',
'Some files could not be uploaded:' => '',
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'The file has been deleted.' => '',
'The requested resource could not be found.' => '',
'The space has been archived.' => '',

View File

@ -57,6 +57,8 @@ return [
'Show less' => '',
'Show more' => '',
'Some files could not be uploaded:' => '',
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'The date has to be in the past.' => '',
'The file has been deleted.' => '',
'The requested resource could not be found.' => '',

File diff suppressed because one or more lines are too long

View File

@ -54,6 +54,8 @@ return [
'Show less' => '',
'Show more' => '',
'Some files could not be uploaded:' => '',
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'The date has to be in the past.' => '',
'The file has been deleted.' => '',
'The requested resource could not be found.' => '',

File diff suppressed because one or more lines are too long

View File

@ -20,6 +20,8 @@ return [
'Export' => '',
'Invalid request method!' => '',
'Select Me' => '',
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'Time Zone' => '',
'<strong>Confirm</strong> Action' => '<strong>Potvrdit</strong> Akci',
'<strong>Latest</strong> updates' => '<strong>Poslední</strong> události',

File diff suppressed because one or more lines are too long

View File

@ -44,6 +44,8 @@ return [
'Show less' => '',
'Show more' => '',
'Some files could not be uploaded:' => '',
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'The date has to be in the past.' => '',
'The file has been deleted.' => '',
'The requested resource could not be found.' => '',

File diff suppressed because one or more lines are too long

View File

@ -1,79 +1,98 @@
<?php
return array (
'<strong>Confirm</strong> Action' => 'Aktion <strong>bestätigen</strong>
/**
* Message translations.
*
* This file is automatically generated by 'yii message/extract' command.
* It contains the localizable messages extracted from source code.
* You may modify this file by translating the extracted messages.
*
* Each array element represents the translation (value) of a message (key).
* If the value is empty, the message is considered as not translated.
* Messages that no longer need translation will have their translations
* enclosed between a pair of '@@' marks.
*
* Message string can be used with plural forms format. Check i18n section
* of the guide for details.
*
* NOTE: this file must be saved in UTF-8 encoding.
*/
return [
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'<strong>Confirm</strong> Action' => 'Aktion <strong>bestätigen</strong>
',
'<strong>Latest</strong> updates' => '<strong>Letzte</strong> Aktualisierungen',
'<strong>Mail</strong> summary' => '<strong>E-Mail</strong> Zusammenfassung',
'Account settings' => 'Kontoeinstellungen',
'Administration' => 'Administration',
'Allow' => 'Erlauben',
'An error occurred while handling your last action. (Handler not found).' => 'Während der letzten Aktion ist ein Fehler aufgetreten. (Handler not found)',
'An unexpected error occurred while loading the search result.' => 'Während des Ladens der Suchergebnisse ist ein unerwarteter Fehler aufgetreten.',
'An unexpected error occurred. If this keeps happening, please contact a site administrator.' => 'Ein unerwarteter Fehler ist aufgetreten. Sollte dieser weiterhin auftreten, kontaktiere den Administrator.',
'An unexpected server error occurred. If this keeps happening, please contact a site administrator.' => 'Ein unerwarteter Serverfehler ist aufgetreten. Sollte dieser weiterhin auftreten, kontaktiere den Administrator.',
'An unknown error occurred while uploading.' => 'Während des Hochladens ist ein unbekannter Fehler aufgetreten.',
'An unknown error occurred while uploading. Hint: check your upload_max_filesize and post_max_size php settings.' => 'Während des Hochladens ist ein unbekannter Fehler aufgetreten. Hinweis: Prüfe die PHP-Einstellungen "upload_max_filesize" und "post_max_size".',
'Back' => 'Zurück',
'Back to dashboard' => 'Zurück zur Übersicht',
'Cancel' => 'Abbrechen',
'Choose language:' => 'Sprache wählen:',
'Close' => 'Schließen',
'Collapse' => 'Einklappen',
'Confirm' => 'Bestätigen',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Die Quelle des Addons muss eine Instanz von HActiveRecordContent oder HActiveRecordContentAddon sein!',
'Copy to clipboard' => 'In die Zwischenablage kopieren',
'Could not determine content container!' => 'Kann Content Container nicht finden.',
'Could not find content of addon!' => 'Der Inhalt des Addons konnte nicht gefunden werden!',
'Default' => 'Standard',
'Deny' => 'Ablehnen',
'Do you really want to perform this action?' => 'Wollen Sie diese Aktion wirklich ausführen?',
'Error' => 'Fehler',
'Error while running your last action (Invalid request method).' => 'Fehler bei der Ausführung der letzten Aktion (Invalid request method).',
'Error:' => 'Fehler:',
'Expand' => 'Erweitern',
'Export' => 'Exportieren',
'Info:' => 'Info:',
'Invalid request method!' => 'Ungültige Anfragemethode!',
'It looks like you may have taken the wrong turn.' => 'Du hast womöglich den falschen Weg eingeschlagen.',
'Language' => 'Sprache',
'Loading...' => 'lädt...',
'Login' => 'Anmelden',
'Logo of {appName}' => 'Logo von {appName}',
'Logout' => 'Ausloggen',
'Menu' => 'Menü',
'Module is not enabled on this content container!' => 'Dieses Modul ist in diesem Content Container nicht aktiviert!',
'My profile' => 'Mein Profil',
'My profile image' => 'Mein Profilbild',
'New profile image' => 'Neues Profilbild',
'Next' => 'Weiter',
'No error information given.' => 'Keine Fehlerbeschreibung verfügbar.',
'Oooops...' => 'Uuuups...',
'Open' => 'Öffnen',
'Please type at least 3 characters' => 'Bitte wengistens 3 Zeichen eingeben',
'Profile dropdown' => 'Profil Dropdown',
'Profile image of {displayName}' => 'Profilbild von {displayName}',
'Profile picture of {displayName}' => 'Profilbild von {displayName}',
'Save' => 'Speichern',
'Saved' => 'Gespeichert',
'Search' => 'Suchen',
'Select Me' => 'Mich auswählen',
'Show less' => 'Weniger anzeigen',
'Show more' => 'Mehr anzeigen',
'Some files could not be uploaded:' => 'Einige Dateien konten nicht hochgeladen werden:',
'Space not found!' => 'Space nicht gefunden!',
'The date has to be in the past.' => 'Datum muss in der Vergangenheit liegen.',
'The file has been deleted.' => 'Die Datei wurde gelöscht.',
'The requested resource could not be found.' => 'Die angeforderte Ressource konnte nicht gefunden werden.',
'The space has been archived.' => 'Der Space wurde archiviert.',
'The space has been unarchived.' => 'Der Space wurde dearchiviert.',
'Time Zone' => 'Zeitzone',
'Toggle comment menu' => 'Kommentarmenü umschalten',
'Toggle panel menu' => 'Panelmenü umschalten',
'Toggle post menu' => 'Beitragsmenü umschalten',
'Toggle stream entry menu' => 'Streameintagsmenü umschalten',
'Unsubscribe' => 'Abbestellen',
'Upload' => 'Hochladen',
'Upload file' => 'Datei hochladen',
'User not found!' => 'Benutzer nicht gefunden!',
'You are not allowed to run this action.' => 'Du hast keine Berechtigung, diese Aktion auszuführen.',
);
'<strong>Latest</strong> updates' => '<strong>Letzte</strong> Aktualisierungen',
'<strong>Mail</strong> summary' => '<strong>E-Mail</strong> Zusammenfassung',
'Account settings' => 'Kontoeinstellungen',
'Administration' => 'Administration',
'Allow' => 'Erlauben',
'An error occurred while handling your last action. (Handler not found).' => 'Während der letzten Aktion ist ein Fehler aufgetreten. (Handler not found)',
'An unexpected error occurred while loading the search result.' => 'Während des Ladens der Suchergebnisse ist ein unerwarteter Fehler aufgetreten.',
'An unexpected error occurred. If this keeps happening, please contact a site administrator.' => 'Ein unerwarteter Fehler ist aufgetreten. Sollte dieser weiterhin auftreten, kontaktiere den Administrator.',
'An unexpected server error occurred. If this keeps happening, please contact a site administrator.' => 'Ein unerwarteter Serverfehler ist aufgetreten. Sollte dieser weiterhin auftreten, kontaktiere den Administrator.',
'An unknown error occurred while uploading.' => 'Während des Hochladens ist ein unbekannter Fehler aufgetreten.',
'An unknown error occurred while uploading. Hint: check your upload_max_filesize and post_max_size php settings.' => 'Während des Hochladens ist ein unbekannter Fehler aufgetreten. Hinweis: Prüfe die PHP-Einstellungen "upload_max_filesize" und "post_max_size".',
'Back' => 'Zurück',
'Back to dashboard' => 'Zurück zur Übersicht',
'Cancel' => 'Abbrechen',
'Choose language:' => 'Sprache wählen:',
'Close' => 'Schließen',
'Collapse' => 'Einklappen',
'Confirm' => 'Bestätigen',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Die Quelle des Addons muss eine Instanz von HActiveRecordContent oder HActiveRecordContentAddon sein!',
'Copy to clipboard' => 'In die Zwischenablage kopieren',
'Could not determine content container!' => 'Kann Content Container nicht finden.',
'Could not find content of addon!' => 'Der Inhalt des Addons konnte nicht gefunden werden!',
'Default' => 'Standard',
'Deny' => 'Ablehnen',
'Do you really want to perform this action?' => 'Wollen Sie diese Aktion wirklich ausführen?',
'Error' => 'Fehler',
'Error while running your last action (Invalid request method).' => 'Fehler bei der Ausführung der letzten Aktion (Invalid request method).',
'Error:' => 'Fehler:',
'Expand' => 'Erweitern',
'Export' => 'Exportieren',
'Info:' => 'Info:',
'Invalid request method!' => 'Ungültige Anfragemethode!',
'It looks like you may have taken the wrong turn.' => 'Du hast womöglich den falschen Weg eingeschlagen.',
'Language' => 'Sprache',
'Loading...' => 'lädt...',
'Login' => 'Anmelden',
'Logo of {appName}' => 'Logo von {appName}',
'Logout' => 'Ausloggen',
'Menu' => 'Menü',
'Module is not enabled on this content container!' => 'Dieses Modul ist in diesem Content Container nicht aktiviert!',
'My profile' => 'Mein Profil',
'My profile image' => 'Mein Profilbild',
'New profile image' => 'Neues Profilbild',
'Next' => 'Weiter',
'No error information given.' => 'Keine Fehlerbeschreibung verfügbar.',
'Oooops...' => 'Uuuups...',
'Open' => 'Öffnen',
'Please type at least 3 characters' => 'Bitte wengistens 3 Zeichen eingeben',
'Profile dropdown' => 'Profil Dropdown',
'Profile image of {displayName}' => 'Profilbild von {displayName}',
'Profile picture of {displayName}' => 'Profilbild von {displayName}',
'Save' => 'Speichern',
'Saved' => 'Gespeichert',
'Search' => 'Suchen',
'Select Me' => 'Mich auswählen',
'Show less' => 'Weniger anzeigen',
'Show more' => 'Mehr anzeigen',
'Some files could not be uploaded:' => 'Einige Dateien konten nicht hochgeladen werden:',
'Space not found!' => 'Space nicht gefunden!',
'The date has to be in the past.' => 'Datum muss in der Vergangenheit liegen.',
'The file has been deleted.' => 'Die Datei wurde gelöscht.',
'The requested resource could not be found.' => 'Die angeforderte Ressource konnte nicht gefunden werden.',
'The space has been archived.' => 'Der Space wurde archiviert.',
'The space has been unarchived.' => 'Der Space wurde dearchiviert.',
'Time Zone' => 'Zeitzone',
'Toggle comment menu' => 'Kommentarmenü umschalten',
'Toggle panel menu' => 'Panelmenü umschalten',
'Toggle post menu' => 'Beitragsmenü umschalten',
'Toggle stream entry menu' => 'Streameintagsmenü umschalten',
'Unsubscribe' => 'Abbestellen',
'Upload' => 'Hochladen',
'Upload file' => 'Datei hochladen',
'User not found!' => 'Benutzer nicht gefunden!',
'You are not allowed to run this action.' => 'Du hast keine Berechtigung, diese Aktion auszuführen.',
];

View File

@ -59,6 +59,8 @@ return [
'Show less' => '',
'Show more' => '',
'Some files could not be uploaded:' => '',
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'The date has to be in the past.' => '',
'The file has been deleted.' => '',
'The requested resource could not be found.' => '',

View File

@ -1,4 +1,4 @@
<?php
return array (
'Invalid content id given!' => '',
'Invalid content id given!' => '¡Se ha introducido un id de contenido no válido!',
);

File diff suppressed because one or more lines are too long

View File

@ -17,16 +17,8 @@
* NOTE: this file must be saved in UTF-8 encoding.
*/
return [
'An unknown error occurred while uploading.' => '',
'An unknown error occurred while uploading. Hint: check your upload_max_filesize and post_max_size php settings.' => '',
'Export' => '',
'Invalid request method!' => '',
'Select Me' => '',
'Time Zone' => '',
'Toggle comment menu' => '',
'Toggle panel menu' => '',
'Toggle post menu' => '',
'Toggle stream entry menu' => '',
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'<strong>Confirm</strong> Action' => '<strong>Confirmar</strong> Acción',
'<strong>Latest</strong> updates' => '<strong>Últimas</strong> actualizaciones',
'<strong>Mail</strong> summary' => '<strong>Resumen</strong> de Correo',
@ -37,25 +29,29 @@ return [
'An unexpected error occurred while loading the search result.' => 'Se ha producido un error inesperado al cargar el resultado de la búsqueda.',
'An unexpected error occurred. If this keeps happening, please contact a site administrator.' => 'Ocurrió un error inesperado. Si esto sigue sucediendo, póngase en contacto con un administrador del sitio.',
'An unexpected server error occurred. If this keeps happening, please contact a site administrator.' => 'Se ha producido un error inesperado en el servidor. Si esto sigue sucediendo, póngase en contacto con un administrador del sitio.',
'An unknown error occurred while uploading.' => 'Se ha producido un error desconocido al cargar.',
'An unknown error occurred while uploading. Hint: check your upload_max_filesize and post_max_size php settings.' => 'Se ha producido un error desconocido al cargar. Consejo: compruebe la configuración de PHP para upload_max_filesize y post_max_size',
'Back' => 'Atrás',
'Back to dashboard' => 'Volver al Panel de Control',
'Cancel' => 'Cancelar',
'Choose language:' => 'Escoge idioma:',
'Choose language:' => 'Escoja idioma:',
'Close' => 'Cerrar',
'Collapse' => 'Cerrar',
'Confirm' => 'Confirmar',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '¡La fuente de Contenido del Complemento debe ser una instancia de HActiveRecordContent ó HActiveRecordContentAddon!',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '¡La fuente de Contenido del Complemento debe ser una instancia de HActiveRecordContent o HActiveRecordContentAddon!',
'Copy to clipboard' => 'Copiar a la Papelera',
'Could not determine content container!' => '¡No se pudo determinar el contenedor de contenido!',
'Could not find content of addon!' => '¡No se pudo encontrar el contenido del complemento!',
'Default' => 'Por Defecto',
'Deny' => 'Denegar',
'Do you really want to perform this action?' => '¿Realmente deseas ejecutar esta acción?',
'Do you really want to perform this action?' => '¿Realmente desea ejecutar esta acción?',
'Error' => 'Error',
'Error while running your last action (Invalid request method).' => 'Error al ejecutar la última acción (método de solicitud no válido).',
'Error:' => 'Error:',
'Expand' => 'Ampliar',
'Export' => 'Exportar',
'Info:' => 'Info:',
'Invalid request method!' => 'Método de la petición no válido',
'It looks like you may have taken the wrong turn.' => 'Parece que puede haber tomado el camino equivocado.',
'Language' => 'Idioma',
'Loading...' => 'Cargando...',
@ -78,6 +74,7 @@ return [
'Save' => 'Guardar',
'Saved' => 'Guardado',
'Search' => 'Buscar',
'Select Me' => 'Seleccione',
'Show less' => 'Mostrar menos',
'Show more' => 'Mostrar más',
'Some files could not be uploaded:' => 'Algunos archivos no se pueden cargar:',
@ -87,6 +84,11 @@ return [
'The requested resource could not be found.' => 'El recurso solicitado no pudo ser encontrado.',
'The space has been archived.' => 'Este espacio ha sido archivado.',
'The space has been unarchived.' => 'Este espacio ha sido desarchivado.',
'Time Zone' => 'Zona horaria',
'Toggle comment menu' => 'Conmutar el menú de comentarios',
'Toggle panel menu' => 'Conmutar el menú de panel',
'Toggle post menu' => 'Conmutar el menú de entrada',
'Toggle stream entry menu' => 'Conmutar el menú de actividad',
'Unsubscribe' => 'Anular la suscripción',
'Upload' => 'Subir',
'Upload file' => 'Cargar archivo',

View File

@ -1,29 +1,12 @@
<?php
/**
* Message translations.
*
* This file is automatically generated by 'yii message/extract' command.
* It contains the localizable messages extracted from source code.
* You may modify this file by translating the extracted messages.
*
* Each array element represents the translation (value) of a message (key).
* If the value is empty, the message is considered as not translated.
* Messages that no longer need translation will have their translations
* enclosed between a pair of '@@' marks.
*
* Message string can be used with plural forms format. Check i18n section
* of the guide for details.
*
* NOTE: this file must be saved in UTF-8 encoding.
*/
return [
'Guest mode not active, please login first.' => '',
'Login required for this section.' => '',
'You are not permitted to access this section.' => '',
'You need admin permissions to access this section.' => '',
'Your user account has not been approved yet, please try again later or contact a network administrator.' => '',
'Your user account is inactive, please login with an active account or contact a network administrator.' => '',
'<strong>Login</strong> required' => 'Es necesario <strong>iniciar sesión</strong>',
'An internal server error occurred.' => 'Un error interno ha ocurrido',
'You are not allowed to perform this action.' => 'Usted no tiene permisos para ejecutar esta acción',
];
return array (
'<strong>Login</strong> required' => 'Es necesario <strong>iniciar sesión</strong>',
'An internal server error occurred.' => 'Un error interno ha ocurrido',
'Guest mode not active, please login first.' => 'El modo de Invitados no está activo. Por favor autentíquese.',
'Login required for this section.' => 'Se requiere autenticación para acceder a esta sección.',
'You are not allowed to perform this action.' => 'Usted no tiene permisos para ejecutar esta acción',
'You are not permitted to access this section.' => 'No está autorizado a acceder a esta sección.',
'You need admin permissions to access this section.' => 'Se necesitan credenciales de administrador para acceder a esta sección.',
'Your user account has not been approved yet, please try again later or contact a network administrator.' => 'Su cuenta de usuario aún no ha sido aprobada. Por favor inténtelo más tarde o póngase en contacto con un administrador de red.',
'Your user account is inactive, please login with an active account or contact a network administrator.' => 'Su cuenta de usuario está inactiva. Por favor autentíquese con una cuenta de usuario activa o contacte con un administrador de red.',
);

File diff suppressed because one or more lines are too long

View File

@ -43,6 +43,8 @@ return [
'Show less' => '',
'Show more' => '',
'Some files could not be uploaded:' => '',
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'The date has to be in the past.' => '',
'The file has been deleted.' => '',
'The requested resource could not be found.' => '',

File diff suppressed because one or more lines are too long

View File

@ -1,78 +1,97 @@
<?php
return array (
'<strong>Confirm</strong> Action' => '<strong>Confirmer</strong> l\'opération',
'<strong>Latest</strong> updates' => '<strong>Dernières</strong> mises à jour',
'<strong>Mail</strong> summary' => '<strong>E-mail</strong> résumé',
'Account settings' => 'Paramètres du compte',
'Administration' => 'Administration',
'Allow' => 'Autoriser',
'An error occurred while handling your last action. (Handler not found).' => 'Une erreur s\'est produite lors de la manipulation de votre dernière action. (Gestionnaire introuvable).',
'An unexpected error occurred while loading the search result.' => 'Une erreur inattendue s\'est produite lors du chargement du résultat de la recherche.',
'An unexpected error occurred. If this keeps happening, please contact a site administrator.' => 'Une erreur inattendue est survenue. Si cela se reproduis, contactez un administrateur du site.',
'An unexpected server error occurred. If this keeps happening, please contact a site administrator.' => 'Une erreur de serveur inattendue s\'est produite. Si cela continue, contactez un administrateur du site.',
'An unknown error occurred while uploading.' => 'Une erreur inconnue s\'est produite lors du chargement de fichier.',
'An unknown error occurred while uploading. Hint: check your upload_max_filesize and post_max_size php settings.' => 'Une erreur inconnue s\'est produite lors du chargement de fichier. Astuce : vérifiez les paramètres php upload_max_filesize et post_max_size.',
'Back' => 'Retour',
'Back to dashboard' => 'Retour au tableau de bord',
'Cancel' => 'Annuler',
'Choose language:' => 'Choisir la langue :',
'Close' => 'Fermer',
'Collapse' => 'Réduire',
'Confirm' => 'Confirmer',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Le contenu d\'un add-on doit être une instance de HActiveRecordContent ou HActiveRecordContentAddon !',
'Copy to clipboard' => 'Copier vers le presse-papier',
'Could not determine content container!' => 'Le contenu du conteneur n\'a pas pu être déterminé !',
'Could not find content of addon!' => 'Le contenu du add-on n\'a pu être trouvé !',
'Default' => 'Défaut',
'Deny' => 'Interdire',
'Do you really want to perform this action?' => 'Voulez-vous vraiment effectuer cette action ?',
'Error' => 'Erreur',
'Error while running your last action (Invalid request method).' => 'Erreur lors de l\'exécution de votre dernière action (méthode de demande non valide).',
'Error:' => 'Erreur :',
'Expand' => 'Agrandir',
'Export' => 'Exporter',
'Info:' => 'Info :',
'Invalid request method!' => 'Méthode de requête invalide !',
'It looks like you may have taken the wrong turn.' => 'Il semble que vous n\'êtes pas au bon endroit.',
'Language' => 'Langue',
'Loading...' => 'Chargement...',
'Login' => 'S\'identifier',
'Logo of {appName}' => 'Logo de {appName}',
'Logout' => 'Se déconnecter',
'Menu' => 'Menu',
'Module is not enabled on this content container!' => 'Le module n\'est pas activé pour ce conteneur !',
'My profile' => 'Mon profil',
'My profile image' => 'Mon image de profil',
'New profile image' => 'Nouvelle image de profil',
'Next' => 'Suivant',
'No error information given.' => 'Aucune information d\'erreur fournie.',
'Oooops...' => 'Oups...',
'Open' => 'Ouvrir',
'Please type at least 3 characters' => 'Merci de taper au moins 3 caractères',
'Profile dropdown' => 'Liste déroulante de profil',
'Profile image of {displayName}' => 'Image de profil de {displayName}',
'Profile picture of {displayName}' => 'Photo de profil de {displayName}',
'Save' => 'Enregistrer',
'Saved' => 'Enregistré',
'Search' => 'Rechercher',
'Select Me' => 'Me choisir',
'Show less' => 'Montrer moins',
'Show more' => 'Montrer plus',
'Some files could not be uploaded:' => 'Certains fichiers n\'ont pas pu être téléchargés :',
'Space not found!' => 'Espace non trouvé !',
'The date has to be in the past.' => 'La date doit être révolue.',
'The file has been deleted.' => 'Le fichier a été supprimé.',
'The requested resource could not be found.' => 'Impossible de trouver la ressource demandée.',
'The space has been archived.' => 'L\'espace à été archivé.',
'The space has been unarchived.' => 'L\'espace à été désarchivé.',
'Time Zone' => 'Fuseau horaire',
'Toggle comment menu' => 'Bascule du menu de commentaire',
'Toggle panel menu' => 'Bascule du menu du panneau',
'Toggle post menu' => 'Bascule du menu de contribution',
'Toggle stream entry menu' => 'Bascule du menu du flux d\'activité',
'Unsubscribe' => 'désinscrition',
'Upload' => 'Ajouter',
'Upload file' => 'Charger un fichier',
'User not found!' => 'Utilisateur non trouvé !',
'You are not allowed to run this action.' => 'Vous n\'êtes pas autorisé à exécuter cette action.',
);
/**
* Message translations.
*
* This file is automatically generated by 'yii message/extract' command.
* It contains the localizable messages extracted from source code.
* You may modify this file by translating the extracted messages.
*
* Each array element represents the translation (value) of a message (key).
* If the value is empty, the message is considered as not translated.
* Messages that no longer need translation will have their translations
* enclosed between a pair of '@@' marks.
*
* Message string can be used with plural forms format. Check i18n section
* of the guide for details.
*
* NOTE: this file must be saved in UTF-8 encoding.
*/
return [
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'<strong>Confirm</strong> Action' => '<strong>Confirmer</strong> l\'opération',
'<strong>Latest</strong> updates' => '<strong>Dernières</strong> mises à jour',
'<strong>Mail</strong> summary' => '<strong>E-mail</strong> résumé',
'Account settings' => 'Paramètres du compte',
'Administration' => 'Administration',
'Allow' => 'Autoriser',
'An error occurred while handling your last action. (Handler not found).' => 'Une erreur s\'est produite lors de la manipulation de votre dernière action. (Gestionnaire introuvable)',
'An unexpected error occurred while loading the search result.' => 'Une erreur inattendue s\'est produite lors du chargement du résultat de la recherche.',
'An unexpected error occurred. If this keeps happening, please contact a site administrator.' => 'Une erreur inattendue s\'est produite. Si cela se reproduit à nouveau, contactez un administrateur du site.',
'An unexpected server error occurred. If this keeps happening, please contact a site administrator.' => 'Une erreur de serveur inattendue s\'est produite. Si cela se reproduit à nouveau, contactez un administrateur du site.',
'An unknown error occurred while uploading.' => 'Une erreur inconnue s\'est produite pendant l\'envoi de fichier.',
'An unknown error occurred while uploading. Hint: check your upload_max_filesize and post_max_size php settings.' => 'Une erreur inconnue s\'est produite lors du chargement de fichier. Vérifiez les paramètres "php upload_max_filesize" et "post_max_size"',
'Back' => 'Retour',
'Back to dashboard' => 'Retour au fil d\'actualités',
'Cancel' => 'Annuler',
'Choose language:' => 'Choisir la langue :',
'Close' => 'Fermer',
'Collapse' => 'Réduire',
'Confirm' => 'Confirmer',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Le contenu d\'un add-on doit être une instance de HActiveRecordContent ou HActiveRecordContentAddon !',
'Copy to clipboard' => 'Copier vers le presse-papier',
'Could not determine content container!' => 'Le contenu du conteneur n\'a pas pu être déterminé !',
'Could not find content of addon!' => 'Le contenu du add-on n\'a pu être trouvé !',
'Default' => 'Défaut',
'Deny' => 'Interdire',
'Do you really want to perform this action?' => 'Voulez-vous vraiment effectuer cette action ?',
'Error' => 'Erreur',
'Error while running your last action (Invalid request method).' => 'Erreur lors de l\'exécution de votre dernière action (méthode de demande non valide).',
'Error:' => 'Erreur :',
'Expand' => 'Agrandir',
'Export' => 'Exporter',
'Info:' => 'Info :',
'Invalid request method!' => 'Méthode de requête invalide.',
'It looks like you may have taken the wrong turn.' => 'Il semble que vous n\'êtes pas au bon endroit...',
'Language' => 'Langue',
'Loading...' => 'Chargement...',
'Login' => 'S\'identifier',
'Logo of {appName}' => 'Logo de {appName}',
'Logout' => 'Se déconnecter',
'Menu' => 'Menu',
'Module is not enabled on this content container!' => 'Le module n\'est pas activé pour ce conteneur.',
'My profile' => 'Mon profil',
'My profile image' => 'Mon image de profil',
'New profile image' => 'Nouvelle image de profil',
'Next' => 'Suivant',
'No error information given.' => 'Aucune information d\'erreur fournie.',
'Oooops...' => 'Oups...',
'Open' => 'Ouvrir',
'Please type at least 3 characters' => 'Merci de taper au moins 3 caractères',
'Profile dropdown' => 'Liste déroulante de profil',
'Profile image of {displayName}' => 'Image de profil de {displayName}',
'Profile picture of {displayName}' => 'Photo de profil de {displayName}',
'Save' => 'Enregistrer',
'Saved' => 'Enregistré',
'Search' => 'Rechercher',
'Select Me' => 'Me choisir',
'Show less' => 'Montrer moins',
'Show more' => 'Montrer plus',
'Some files could not be uploaded:' => 'Certains fichiers n\'ont pas pu être téléchargés :',
'Space not found!' => 'Espace non trouvé.',
'The date has to be in the past.' => 'La date doit être révolue.',
'The file has been deleted.' => 'Le fichier a été supprimé.',
'The requested resource could not be found.' => 'Impossible de trouver la ressource demandée.',
'The space has been archived.' => 'L\'espace à été archivé.',
'The space has been unarchived.' => 'L\'espace à été désarchivé.',
'Time Zone' => 'Fuseau horaire',
'Toggle comment menu' => 'Bascule du menu de commentaire',
'Toggle panel menu' => 'Bascule du menu du panneau',
'Toggle post menu' => 'Bascule du menu de contribution',
'Toggle stream entry menu' => 'Bascule du menu du flux d\'activité',
'Unsubscribe' => 'Désinscription',
'Upload' => 'Ajouter',
'Upload file' => 'Envoyer un fichier',
'User not found!' => 'Utilisateur non trouvé.',
'You are not allowed to run this action.' => 'Vous n\'êtes pas autorisé à exécuter cette action.',
];

View File

@ -1,21 +1,4 @@
<?php
/**
* Message translations.
*
* This file is automatically generated by 'yii message/extract' command.
* It contains the localizable messages extracted from source code.
* You may modify this file by translating the extracted messages.
*
* Each array element represents the translation (value) of a message (key).
* If the value is empty, the message is considered as not translated.
* Messages that no longer need translation will have their translations
* enclosed between a pair of '@@' marks.
*
* Message string can be used with plural forms format. Check i18n section
* of the guide for details.
*
* NOTE: this file must be saved in UTF-8 encoding.
*/
return [
'Invalid content id given!' => '',
];
return array (
'Invalid content id given!' => 'Navedeni ID sadržaj nije valjan!',
);

View File

@ -17,79 +17,81 @@
* NOTE: this file must be saved in UTF-8 encoding.
*/
return [
'<strong>Confirm</strong> Action' => '',
'<strong>Latest</strong> updates' => '',
'<strong>Mail</strong> summary' => '',
'Account settings' => '',
'Administration' => '',
'Allow' => '',
'An error occurred while handling your last action. (Handler not found).' => '',
'An unexpected error occurred while loading the search result.' => '',
'An unexpected error occurred. If this keeps happening, please contact a site administrator.' => '',
'An unexpected server error occurred. If this keeps happening, please contact a site administrator.' => '',
'An unknown error occurred while uploading.' => '',
'An unknown error occurred while uploading. Hint: check your upload_max_filesize and post_max_size php settings.' => '',
'Back' => '',
'Back to dashboard' => '',
'Choose language:' => '',
'Close' => '',
'Collapse' => '',
'Confirm' => '',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '',
'Copy to clipboard' => '',
'Could not determine content container!' => '',
'Could not find content of addon!' => '',
'Default' => '',
'Deny' => '',
'Do you really want to perform this action?' => '',
'Error' => '',
'Error while running your last action (Invalid request method).' => '',
'Error:' => '',
'Expand' => '',
'Export' => '',
'Info:' => '',
'Invalid request method!' => '',
'It looks like you may have taken the wrong turn.' => '',
'Language' => '',
'Loading...' => '',
'Login' => '',
'Logo of {appName}' => '',
'Logout' => '',
'Menu' => '',
'Module is not enabled on this content container!' => '',
'My profile' => '',
'My profile image' => '',
'New profile image' => '',
'Next' => '',
'No error information given.' => '',
'Oooops...' => '',
'Open' => '',
'Please type at least 3 characters' => '',
'Profile dropdown' => '',
'Profile image of {displayName}' => '',
'Profile picture of {displayName}' => '',
'Saved' => '',
'Search' => '',
'Select Me' => '',
'Show less' => '',
'Show more' => '',
'Some files could not be uploaded:' => '',
'Space not found!' => '',
'The date has to be in the past.' => '',
'The file has been deleted.' => '',
'The requested resource could not be found.' => '',
'The space has been archived.' => '',
'The space has been unarchived.' => '',
'Time Zone' => '',
'Toggle comment menu' => '',
'Toggle panel menu' => '',
'Toggle post menu' => '',
'Toggle stream entry menu' => '',
'Unsubscribe' => '',
'Upload' => '',
'Upload file' => '',
'User not found!' => '',
'You are not allowed to run this action.' => '',
'Cancel' => 'poništi',
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'<strong>Confirm</strong> Action' => '<strong>Potvrdi</strong> akciju',
'<strong>Latest</strong> updates' => '<strong>Zadnje</strong> ažuriranje',
'<strong>Mail</strong> summary' => '<strong>Mail</strong> sažetak',
'Account settings' => 'Postavke računa',
'Administration' => 'Administracija',
'Allow' => 'Dopusti',
'An error occurred while handling your last action. (Handler not found).' => 'Došlo je do pogreške pri rukovanju vašom posljednjom radnjom. (Handler nije pronađen).',
'An unexpected error occurred while loading the search result.' => 'Došlo je do neočekivane pogreške prilikom učitavanja rezultata pretraživanja.',
'An unexpected error occurred. If this keeps happening, please contact a site administrator.' => 'Došlo je do neočekivane pogreške. Ako se to nastavi, kontaktirajte administratora web mjesta.',
'An unexpected server error occurred. If this keeps happening, please contact a site administrator.' => 'Došlo je do neočekivane pogreške poslužitelja. Ako se to nastavi, kontaktirajte administratora web mjesta.',
'An unknown error occurred while uploading.' => 'Došlo je do nepoznate pogreške prilikom prijenosa.',
'An unknown error occurred while uploading. Hint: check your upload_max_filesize and post_max_size php settings.' => 'Došlo je do nepoznate pogreške prilikom prijenosa. Savjet: provjerite postavke php postavki upload_max_filesize i post_max_size.',
'Back' => 'Povratak',
'Back to dashboard' => 'Povratak na upravljačku ploču',
'Cancel' => 'Poništi',
'Choose language:' => 'Odaberite jezik:',
'Close' => 'Zatvori',
'Collapse' => 'Spusti',
'Confirm' => 'Potvrdi',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Izvor sadržaja Addon mora biti primjerak HActiveRecordContent ili HActiveRecordContentAddon!',
'Copy to clipboard' => 'Kopirati u međuspremnik',
'Could not determine content container!' => 'Nije moguće odrediti spremnik sadržaja!',
'Could not find content of addon!' => 'Nije moguće pronaći sadržaj addona!',
'Default' => 'Zadano',
'Deny' => 'Odbiti',
'Do you really want to perform this action?' => 'Želite li zaista uraditi ovu akciju?',
'Error' => 'Error',
'Error while running your last action (Invalid request method).' => 'Pogreška prilikom izvođenja zadnje radnje (nevažeći način zahtjeva).',
'Error:' => 'Error:',
'Expand' => 'Proširi',
'Export' => 'Izvoz',
'Info:' => 'Info:',
'Invalid request method!' => 'Nevažeći način zahtjeva!',
'It looks like you may have taken the wrong turn.' => 'Izgleda da ste se pogrešno skrenuli.',
'Language' => 'Jezik',
'Loading...' => 'Učitavam...',
'Login' => 'Prijava',
'Logo of {appName}' => 'Logo {appName}',
'Logout' => 'Odjava',
'Menu' => 'Izbornik',
'Module is not enabled on this content container!' => 'Modul nije omogućen na ovom spremniku sadržaja!',
'My profile' => 'Moj profil',
'My profile image' => 'Moja profilna slika',
'New profile image' => 'Nova profilna slika',
'Next' => 'Dalje',
'No error information given.' => 'Nema podataka o pogrešci.',
'Oooops...' => 'Oooops...',
'Open' => 'Otvori',
'Please type at least 3 characters' => 'Upišite najmanje 3 znaka',
'Profile dropdown' => 'Padajući izbornik profila',
'Profile image of {displayName}' => 'Profilna slika od {displayName}',
'Profile picture of {displayName}' => 'Profilna slika od {displayName}',
'Save' => 'Spremi',
'Saved' => 'Spremljeno',
'Search' => 'Pretraži',
'Select Me' => 'Izaberi mene',
'Show less' => 'Prikaži manje',
'Show more' => 'Prikaži više',
'Some files could not be uploaded:' => 'Neke datoteke nisu prenesene:',
'Space not found!' => 'Prostor nije pronađen!',
'The date has to be in the past.' => 'Datum mora biti u prošlosti.',
'The file has been deleted.' => 'Datoteka je izbrisana.',
'The requested resource could not be found.' => 'Traženi resurs nije moguće pronaći.',
'The space has been archived.' => 'Prostor je arhiviran.',
'The space has been unarchived.' => 'Prostor je od-arhiviran.',
'Time Zone' => 'Vremenska zona',
'Toggle comment menu' => 'Prebacivanje izbornika komentara',
'Toggle panel menu' => 'Prebacivanje izbornika na ploči',
'Toggle post menu' => 'Prelazak na izbornik posta',
'Toggle stream entry menu' => 'Prebacivanje izbornika unosa u stream',
'Unsubscribe' => 'Otkažite pretplatu',
'Upload' => 'Dodaj',
'Upload file' => 'Dodaj datoteku',
'User not found!' => 'Korisnik nije pronađen!',
'You are not allowed to run this action.' => 'Nije vam dozvoljena ova akcija.',
];

View File

@ -1,29 +1,12 @@
<?php
/**
* Message translations.
*
* This file is automatically generated by 'yii message/extract' command.
* It contains the localizable messages extracted from source code.
* You may modify this file by translating the extracted messages.
*
* Each array element represents the translation (value) of a message (key).
* If the value is empty, the message is considered as not translated.
* Messages that no longer need translation will have their translations
* enclosed between a pair of '@@' marks.
*
* Message string can be used with plural forms format. Check i18n section
* of the guide for details.
*
* NOTE: this file must be saved in UTF-8 encoding.
*/
return [
'<strong>Login</strong> required' => '',
'An internal server error occurred.' => '',
'Guest mode not active, please login first.' => '',
'Login required for this section.' => '',
'You are not allowed to perform this action.' => '',
'You are not permitted to access this section.' => '',
'You need admin permissions to access this section.' => '',
'Your user account has not been approved yet, please try again later or contact a network administrator.' => '',
'Your user account is inactive, please login with an active account or contact a network administrator.' => '',
];
return array (
'<strong>Login</strong> required' => '<strong>Prijava</strong> potrebna',
'An internal server error occurred.' => 'Došlo je do unutarnje pogreške poslužitelja.',
'Guest mode not active, please login first.' => 'Način rada Gosta nije aktivan, prvo se prijavite.',
'Login required for this section.' => 'Prijava potrebna za ovaj odjeljak.',
'You are not allowed to perform this action.' => 'Nije vam dozvoljena ova akcija.',
'You are not permitted to access this section.' => 'Nije vam dopušteno pristupiti ovom odjeljku.',
'You need admin permissions to access this section.' => 'Trebate administratorske ovlasti za pristup ovom odjeljku.',
'Your user account has not been approved yet, please try again later or contact a network administrator.' => 'Vaš korisnički račun još nije odobren, pokušajte ponovo kasnije ili se obratite mrežnom administratoru.',
'Your user account is inactive, please login with an active account or contact a network administrator.' => 'Vaš korisnički račun nije aktivan, prijavite se aktivnim računom ili se obratite mrežnom administratoru.',
);

View File

@ -1,51 +1,34 @@
<?php
/**
* Message translations.
*
* This file is automatically generated by 'yii message' command.
* It contains the localizable messages extracted from source code.
* You may modify this file by translating the extracted messages.
*
* Each array element represents the translation (value) of a message (key).
* If the value is empty, the message is considered as not translated.
* Messages that no longer need translation will have their translations
* enclosed between a pair of '@@' marks.
*
* Message string can be used with plural forms format. Check i18n section
* of the guide for details.
*
* NOTE: this file must be saved in UTF-8 encoding.
*/
return [
'Add image/file' => '',
'Add link' => '',
'Bold' => '',
'Close' => '',
'Code' => '',
'Enter a url (e.g. http://example.com)' => '',
'Heading' => '',
'Image' => '',
'Image/File' => '',
'Insert Hyperlink' => '',
'Insert Image Hyperlink' => '',
'Italic' => '',
'List' => '',
'Please wait while uploading...' => '',
'Preview' => '',
'Quote' => '',
'Target' => '',
'Title' => '',
'Title of your link' => '',
'URL/Link' => '',
'code text here' => '',
'emphasized text' => '',
'enter image description here' => '',
'enter image title here' => '',
'enter link description here' => '',
'heading text' => '',
'list text here' => '',
'quote here' => '',
'strong text' => '',
'Unordered List' => '',
'Ordered List' => '',
];
return array (
'Add image/file' => 'Dodaj sliku / datoteku',
'Add link' => 'Dodaj poveznicu',
'Bold' => 'Bold',
'Close' => 'Zatvori',
'Code' => 'Kod',
'Enter a url (e.g. http://example.com)' => 'Unesite URL (e.g. http://example.com)',
'Heading' => 'Naslov',
'Image' => 'Slika',
'Image/File' => 'Slika/Datoteka',
'Insert Hyperlink' => 'Unesi hyperlink',
'Insert Image Hyperlink' => 'Unesi hyperlink slike',
'Italic' => 'Italic',
'List' => 'Lista',
'Ordered List' => 'Uređeni popis',
'Please wait while uploading...' => 'Pričekajte dok se učitava...',
'Preview' => 'Pregled',
'Quote' => 'Citat',
'Target' => 'Cilj',
'Title' => 'Naziv',
'Title of your link' => 'Naziv vašeg linka',
'URL/Link' => 'URL/Link',
'Unordered List' => 'Neuređeni popis',
'code text here' => 'tekst koda ovdje',
'emphasized text' => 'naglasi tekst',
'enter image description here' => 'unesite opis slike',
'enter image title here' => 'unesite naziv slike',
'enter link description here' => 'unesite opis linka',
'heading text' => 'tekst naslova',
'list text here' => 'unesite popis tekstova',
'quote here' => 'ovdje navedite',
'strong text' => 'jaki tekst',
);

View File

@ -46,6 +46,8 @@ return [
'Select Me' => '',
'Show less' => '',
'Some files could not be uploaded:' => '',
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'The file has been deleted.' => '',
'The requested resource could not be found.' => '',
'The space has been archived.' => '',

File diff suppressed because one or more lines are too long

View File

@ -54,6 +54,8 @@ return [
'Show more' => '',
'Some files could not be uploaded:' => '',
'Space not found!' => '',
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'The date has to be in the past.' => '',
'The file has been deleted.' => '',
'The requested resource could not be found.' => '',

File diff suppressed because one or more lines are too long

View File

@ -51,6 +51,8 @@ return [
'Show less' => '',
'Show more' => '',
'Some files could not be uploaded:' => '',
'Text could not be copied to clipboard' => '',
'Text has been copied to clipboard' => '',
'The date has to be in the past.' => '',
'The file has been deleted.' => '',
'The requested resource could not be found.' => '',

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More