mirror of
https://github.com/humhub/humhub.git
synced 2025-01-17 14:18:27 +01:00
Merge branch 'v1.2-dev' of https://github.com/humhub/humhub into v1.2-dev
This commit is contained in:
commit
08fea57851
@ -23,6 +23,7 @@
|
||||
"cebe/markdown": "1.0.2",
|
||||
"yiisoft/yii2-jui": "^2.0",
|
||||
"zendframework/zend-http": "*",
|
||||
"jbroadway/urlify": "^1.0",
|
||||
"nqxcode/zendsearch": "^2.0",
|
||||
"xj/yii2-jplayer-widget": "*",
|
||||
"zendframework/zend-ldap": "^2.5",
|
||||
|
63
js/app.js
63
js/app.js
@ -125,11 +125,23 @@ function HashTable(obj) {
|
||||
|
||||
|
||||
/**
|
||||
* setModalLoader
|
||||
*
|
||||
* Change buttons with loader
|
||||
* To allow other frameworks to overlay focusable nodes over an active modal we have
|
||||
* to explicitly allow ith within this overwritten function.
|
||||
*
|
||||
*/
|
||||
$.fn.modal.Constructor.prototype.enforceFocus = function () {
|
||||
var that = this;
|
||||
$(document).on('focusin.modal', function (e) {
|
||||
if ($(e.target).hasClass('select2-input') || $(e.target).hasClass('hexInput')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (that.$element[0] !== e.target && !that.$element.has(e.target).length) {
|
||||
that.$element.focus();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function setModalLoader() {
|
||||
$(".modal-footer .btn").hide();
|
||||
$(".modal-footer .loader").removeClass("hidden");
|
||||
@ -143,14 +155,53 @@ $(document).ready(function () {
|
||||
$(this).removeData('bs.modal');
|
||||
|
||||
// just close modal and reset modal content to default (shows the loader)
|
||||
$(this).html('<div class="modal-dialog"><div class="modal-content"><div class="modal-body"><div class="loader"><div class="sk-spinner sk-spinner-three-bounce"><div class="sk-bounce1"></div><div class="sk-bounce2"></div><div class="sk-bounce3"></div></div></div></div></div></div>');
|
||||
})
|
||||
$(this).html('<div class="modal-dialog"><div class="modal-content"><div class="modal-body">\n\
|
||||
<div class="loader"><div class="sk-spinner sk-spinner-three-bounce"><div class="sk-bounce1"></div><div class="sk-bounce2"></div><div class="sk-bounce3"></div></div></div></div></div></div>');
|
||||
});
|
||||
|
||||
// set Modal handler to all modal links
|
||||
setModalHandler();
|
||||
|
||||
initPlugins();
|
||||
|
||||
$('a[data-ui-loader], button[data-ui-loader]').on('click', function () {
|
||||
var $this = $(this);
|
||||
|
||||
if($this.find('.loader').length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
//Adopt current color for the loader animation
|
||||
var color = $this.css('color') || '#ffffff';
|
||||
var $loader = $('<span class="loader"><span class="sk-spinner sk-spinner-three-bounce"><span class="sk-bounce1"></span><span class="sk-bounce2"></span><span class="sk-bounce3"></span></span></span>');
|
||||
|
||||
//Align bouncer animation color and size
|
||||
$loader.find('.sk-bounce1, .sk-bounce2, .sk-bounce3')
|
||||
.addClass('disabled')
|
||||
.css( {'background-color': color, 'width': '10px', 'height': '10px'});
|
||||
|
||||
//The loader does have some margin we have to hide
|
||||
$this.css('overflow', 'hidden');
|
||||
$this.addClass('disabled');
|
||||
|
||||
//Prevent the container from resizing
|
||||
$this.css('min-width', this.getBoundingClientRect().width);
|
||||
$this.data('text', $this.text());
|
||||
$this.html($loader);
|
||||
});
|
||||
|
||||
$(document).on('afterValidate', function(evt, messages, errors) {
|
||||
if(errors.length) {
|
||||
$('[data-ui-loader]').each(function() {
|
||||
var $this = $(this);
|
||||
if($this.find('.loader').length) {
|
||||
$this.html($this.data('text'));
|
||||
$this.removeClass('disabled');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
function setModalHandler() {
|
||||
@ -162,7 +213,7 @@ function setModalHandler() {
|
||||
$(document).on('click.humhub', "a[data-target='#globalModal']", function (ev) {
|
||||
ev.preventDefault();
|
||||
var options = {
|
||||
'show' : true,
|
||||
'show': true,
|
||||
'backdrop': $(this).data('backdrop')
|
||||
}
|
||||
$("#globalModal").modal(options);
|
||||
|
36
js/select2-extension.js
Normal file
36
js/select2-extension.js
Normal file
@ -0,0 +1,36 @@
|
||||
//This file contains style alignments for the select2 multi dropdown js framework.
|
||||
$(document).ready(function () {
|
||||
$.fn.select2.defaults = {};
|
||||
|
||||
//We have to overwrite the the result gui after every change
|
||||
$('.multiselect_dropdown').select2({}).on('change', function () {
|
||||
$(this).trigger('update');
|
||||
}).on('select2:open', function () {
|
||||
$(this).data('isOpen', true);
|
||||
}).on('select2:close', function () {
|
||||
$(this).data('isOpen', false);
|
||||
}).on('update', function () {
|
||||
var $container = $(this).next('.select2-container');
|
||||
var $choices = $container.find('.select2-selection__choice');
|
||||
$choices.addClass('userInput');
|
||||
var $closeButton = $('<i class="fa fa-times-circle"></i>');
|
||||
$closeButton.on('click', function () {
|
||||
$(this).siblings('span[role="presentation"]').trigger('click');
|
||||
});
|
||||
$choices.append($closeButton);
|
||||
});
|
||||
|
||||
//For highlighting the input
|
||||
$(".select2-container").on("focusin", function () {
|
||||
$(this).find('.select2-selection').addClass('select2-selection--focus');
|
||||
});
|
||||
|
||||
//Since the focusout of the ontainer is called when the dropdown is opened we have to use this focusout
|
||||
$(document).on('focusout', '.select2-search__field', function () {
|
||||
if (!$(this).closest('.select2-container').prev('.multiselect_dropdown').data('isOpen')) {
|
||||
$(this).closest('.select2-selection').removeClass('select2-selection--focus');
|
||||
}
|
||||
});
|
||||
|
||||
$('.multiselect_dropdown').trigger('update');
|
||||
});
|
95
js/tabbedForm.js
Normal file
95
js/tabbedForm.js
Normal file
@ -0,0 +1,95 @@
|
||||
$(document).ready(function () {
|
||||
/**
|
||||
* Searches a
|
||||
* @param {type} $form
|
||||
* @returns {$lastFieldSet$fieldSet}
|
||||
*/
|
||||
var getPreparedFieldSets = function ($form) {
|
||||
var result = {};
|
||||
var $lastFieldSet;
|
||||
|
||||
// Assamble all fieldsets with label
|
||||
$form.find('fieldset').each(function () {
|
||||
var $fieldSet = $(this);
|
||||
$fieldSet.hide();
|
||||
|
||||
var legend = $fieldSet.children('legend').text();
|
||||
if (legend && legend.length) {
|
||||
// Make sure all fieldsets are direct children
|
||||
result[legend] = $lastFieldSet = $fieldSet;
|
||||
} else if($lastFieldSet) {
|
||||
// We append form groups to the previous fieldset if no label is defined
|
||||
$lastFieldSet.append($fieldSet.children(".form-group"));
|
||||
}
|
||||
});
|
||||
return result;
|
||||
};
|
||||
|
||||
/**
|
||||
* Check for errors in a specific category
|
||||
* @param _object
|
||||
* @returns {boolean}
|
||||
*/
|
||||
var hasErrors = function($fieldSet) {
|
||||
var hasError = false;
|
||||
|
||||
$fieldSet.children(".form-group").each(function (index, value) {
|
||||
|
||||
// if an input have the class "error"
|
||||
if ($(this).children('.form-control').hasClass("error")) {
|
||||
hasError = true;
|
||||
return false; // stop loop/function
|
||||
}
|
||||
});
|
||||
return hasError;
|
||||
|
||||
};
|
||||
|
||||
$('[data-ui-tabbed-form]').each(function () {
|
||||
var activeTab = 0;
|
||||
|
||||
var $form = $(this);
|
||||
var $tabContent = $('<div class="tab-content"></div>');
|
||||
var $tabs = $('<ul id="profile-tabs" class="nav nav-tabs" data-tabs="tabs"></ul>');
|
||||
$form.prepend($tabContent);
|
||||
$form.prepend($tabs);
|
||||
|
||||
var index = 0;
|
||||
$.each(getPreparedFieldSets($form), function(label, $fieldSet) {
|
||||
// activate this tab if there are any errors
|
||||
if (hasErrors($fieldSet)) {
|
||||
activeTab = index;
|
||||
}
|
||||
|
||||
// build tab structure
|
||||
$tabs.append('<li><a href="#tab-' + index + '" data-toggle="tab">' + label + '</a></li>');
|
||||
$tabContent.append('<div class="tab-pane" data-tab-index="'+index+'" id="tab-' + index + '"></div>');
|
||||
|
||||
// clone inputs from fieldSet into our tab structure
|
||||
var $inputs = $fieldSet.children(".form-group");
|
||||
$('#tab-' + index).html($inputs.clone());
|
||||
|
||||
// Remove old fieldset
|
||||
$fieldSet.remove();
|
||||
|
||||
index++;
|
||||
});
|
||||
|
||||
// prepend error summary to form if present
|
||||
if ($('.errorSummary').length != null) {
|
||||
var _errorSummary = $('.errorSummary').clone();
|
||||
$('.errorSummary').remove();
|
||||
$form.prepend(_errorSummary);
|
||||
}
|
||||
|
||||
// activate the first tab or the tab with errors
|
||||
$tabs.find('a[href="#tab-' + activeTab + '"]').tab('show');
|
||||
});
|
||||
|
||||
$(document).on('afterValidate', function(evt, messages, errors) {
|
||||
if(errors.length) {
|
||||
var index = $(errors[0].container).closest('.tab-pane').data('tab-index');
|
||||
$('a[href="#tab-' + index + '"]').tab('show');
|
||||
}
|
||||
});
|
||||
});
|
34
protected/humhub/assets/Select2ExtensionAsset.php
Normal file
34
protected/humhub/assets/Select2ExtensionAsset.php
Normal file
@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\assets;
|
||||
|
||||
use yii\web\AssetBundle;
|
||||
|
||||
/**
|
||||
* jquery-knob
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
class Select2ExtensionAsset extends AssetBundle
|
||||
{
|
||||
|
||||
public $jsOptions = ['position' => \yii\web\View::POS_BEGIN];
|
||||
|
||||
public $basePath = '@webroot';
|
||||
public $baseUrl = '@web';
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $js = ['js/select2-extension.js'];
|
||||
|
||||
public $depends = [
|
||||
'humhub\assets\Select2Asset'
|
||||
];
|
||||
}
|
28
protected/humhub/assets/TabbedFormAsset.php
Normal file
28
protected/humhub/assets/TabbedFormAsset.php
Normal file
@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\assets;
|
||||
|
||||
use yii\web\AssetBundle;
|
||||
|
||||
/**
|
||||
* jquery-knob
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
class TabbedFormAsset extends AssetBundle
|
||||
{
|
||||
public $basePath = '@webroot';
|
||||
public $baseUrl = '@web';
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $js = ['js/tabbedForm.js'];
|
||||
|
||||
}
|
@ -15,7 +15,7 @@ use humhub\models\Setting;
|
||||
|
||||
/**
|
||||
* Cronjobs
|
||||
*
|
||||
*
|
||||
* @author Luke
|
||||
*/
|
||||
class CronController extends Controller
|
||||
@ -41,7 +41,7 @@ class CronController extends Controller
|
||||
$this->trigger(self::EVENT_ON_HOURLY_RUN);
|
||||
|
||||
$this->stdout("\n\nAll cron tasks finished.\n\n", Console::FG_GREEN);
|
||||
Setting::Set('cronLastHourlyRun', time());
|
||||
Yii::$app->settings->set('cronLastHourlyRun', time());
|
||||
|
||||
return self::EXIT_CODE_NORMAL;
|
||||
}
|
||||
@ -56,7 +56,7 @@ class CronController extends Controller
|
||||
$this->trigger(self::EVENT_ON_DAILY_RUN);
|
||||
|
||||
$this->stdout("\n\nAll cron tasks finished.\n\n", Console::FG_GREEN);
|
||||
Setting::Set('cronLastDailyRun', time());
|
||||
Yii::$app->settings->set('cronLastDailyRun', time());
|
||||
|
||||
return self::EXIT_CODE_NORMAL;
|
||||
}
|
||||
|
@ -162,7 +162,7 @@ class HForm extends \yii\base\Component
|
||||
$output = "";
|
||||
foreach ($buttons as $buttonName => $definition) {
|
||||
if ($definition['type'] == 'submit') {
|
||||
$output .= \yii\helpers\Html::submitButton($definition['label'], ['name' => $buttonName, 'class' => $definition['class']]);
|
||||
$output .= \yii\helpers\Html::submitButton($definition['label'], ['name' => $buttonName, 'class' => $definition['class'], 'data-ui-loader' => '']);
|
||||
$output .= " ";
|
||||
}
|
||||
}
|
||||
@ -193,6 +193,7 @@ class HForm extends \yii\base\Component
|
||||
|
||||
if (isset($definition['readonly']) && $definition['readonly']) {
|
||||
$options['readOnly'] = true;
|
||||
$options['disabled'] = true;
|
||||
}
|
||||
|
||||
if (isset($definition['value'])) {
|
||||
|
@ -31,7 +31,7 @@ class Application extends \yii\web\Application
|
||||
* Check if it's already installed - if not force controller module
|
||||
*/
|
||||
if (!$this->params['installed'] && $this->controller->module != null && $this->controller->module->id != 'installer') {
|
||||
$this->controller->redirect(\yii\helpers\Url::to(['/installer/index']));
|
||||
$this->controller->redirect(['/installer/index']);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -33,6 +33,20 @@ class Module extends \yii\base\Module
|
||||
*/
|
||||
public $resourcesPath = 'assets';
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
parent::init();
|
||||
|
||||
// Set settings component
|
||||
$this->set('settings', [
|
||||
'class' => SettingsManager::className(),
|
||||
'moduleId' => $this->id
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns modules name provided by module.json file
|
||||
*
|
||||
@ -82,7 +96,7 @@ class Module extends \yii\base\Module
|
||||
|
||||
/**
|
||||
* Returns image url for this module
|
||||
* Place your modules image in assets/module_image.png
|
||||
* Place your modules image in <resourcesPath>/module_image.png
|
||||
*
|
||||
* @return String Image Url
|
||||
*/
|
||||
@ -91,7 +105,8 @@ class Module extends \yii\base\Module
|
||||
$moduleImageFile = $this->getBasePath() . '/' . $this->resourcesPath . '/module_image.png';
|
||||
|
||||
if (is_file($moduleImageFile)) {
|
||||
return $this->getAssetsUrl() . '/module_image.png';
|
||||
list($path, $url) = Yii::$app->assetManager->publish($moduleImageFile);
|
||||
return $url;
|
||||
}
|
||||
|
||||
return Yii::getAlias("@web/img/default_module.jpg");
|
||||
@ -110,20 +125,14 @@ class Module extends \yii\base\Module
|
||||
|
||||
/**
|
||||
* Enables this module
|
||||
* It will be available on the next request.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function enable()
|
||||
{
|
||||
$moduleEnabled = ModuleEnabled::findOne(['module_id' => $this->id]);
|
||||
if ($moduleEnabled == null) {
|
||||
$moduleEnabled = new ModuleEnabled();
|
||||
$moduleEnabled->module_id = $this->id;
|
||||
$moduleEnabled->save();
|
||||
}
|
||||
|
||||
Yii::$app->moduleManager->enable($this);
|
||||
$this->migrate();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -135,11 +144,7 @@ class Module extends \yii\base\Module
|
||||
*/
|
||||
public function disable()
|
||||
{
|
||||
// Disable module in database
|
||||
$moduleEnabled = ModuleEnabled::findOne(['module_id' => $this->id]);
|
||||
if ($moduleEnabled != null) {
|
||||
$moduleEnabled->delete();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove database tables
|
||||
@ -173,24 +178,23 @@ class Module extends \yii\base\Module
|
||||
}
|
||||
}
|
||||
|
||||
foreach (\humhub\modules\content\models\ContentContainerSetting::findAll(['module_id' => $this->id]) as $containerSetting) {
|
||||
$containerSetting->delete();
|
||||
}
|
||||
|
||||
/*
|
||||
HSetting::model()->deleteAllByAttributes(array('module_id' => $this->getId()));
|
||||
SpaceSetting::model()->deleteAllByAttributes(array('module_id' => $this->getId()));
|
||||
UserSetting::model()->deleteAllByAttributes(array('module_id' => $this->getId()));
|
||||
foreach (\humhub\models\Setting::findAll(['module_id' => $this->id]) as $containerSetting) {
|
||||
$containerSetting->delete();
|
||||
}
|
||||
|
||||
// Delete also records with disabled state from SpaceApplicationModule Table
|
||||
foreach (SpaceApplicationModule::model()->findAllByAttributes(array('module_id' => $this->getId())) as $sam) {
|
||||
$sam->delete();
|
||||
}
|
||||
foreach (\humhub\modules\user\models\Module::findAll(['module_id' => $this->id]) as $userModule) {
|
||||
$userModule->delete();
|
||||
}
|
||||
|
||||
// Delete also records with disabled state from UserApplicationModule Table
|
||||
foreach (UserApplicationModule::model()->findAllByAttributes(array('module_id' => $this->getId())) as $uam) {
|
||||
$uam->delete();
|
||||
}
|
||||
foreach (\humhub\modules\space\models\Module::findAll(['module_id' => $this->id]) as $spaceModule) {
|
||||
$spaceModule->delete();
|
||||
}
|
||||
|
||||
ModuleManager::flushCache();
|
||||
*/
|
||||
Yii::$app->moduleManager->disable($this);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -251,7 +255,7 @@ class Module extends \yii\base\Module
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a list of notification classes this module provides.
|
||||
*
|
||||
|
@ -13,6 +13,7 @@ use yii\base\Exception;
|
||||
use yii\base\Event;
|
||||
use yii\base\InvalidConfigException;
|
||||
use humhub\components\bootstrap\ModuleAutoLoader;
|
||||
use humhub\models\ModuleEnabled;
|
||||
|
||||
/**
|
||||
* ModuleManager handles all installed modules.
|
||||
@ -114,6 +115,8 @@ class ModuleManager extends \yii\base\Component
|
||||
if (isset($config['namespace'])) {
|
||||
Yii::setAlias('@' . str_replace('\\', '/', $config['namespace']), $basePath);
|
||||
}
|
||||
Yii::setAlias('@' . $config['id'], $basePath);
|
||||
|
||||
|
||||
if (!Yii::$app->params['installed'] && $isInstallerModule) {
|
||||
$this->enabledModules[] = $config['id'];
|
||||
@ -145,14 +148,12 @@ class ModuleManager extends \yii\base\Component
|
||||
|
||||
// Add config file values to module
|
||||
if (isset(Yii::$app->modules[$config['id']]) && is_array(Yii::$app->modules[$config['id']])) {
|
||||
$moduleConfig = yii\helpers\ArrayHelper::merge($moduleConfig, Yii::$app->modules[$config['id']]);
|
||||
$moduleConfig = \yii\helpers\ArrayHelper::merge($moduleConfig, Yii::$app->modules[$config['id']]);
|
||||
}
|
||||
|
||||
// Register Yii Module
|
||||
Yii::$app->setModule($config['id'], $moduleConfig);
|
||||
|
||||
|
||||
|
||||
// Register Event Handlers
|
||||
if (isset($config['events'])) {
|
||||
foreach ($config['events'] as $event) {
|
||||
@ -295,13 +296,52 @@ class ModuleManager extends \yii\base\Component
|
||||
|
||||
$backupFolderName = $moduleBackupFolder . DIRECTORY_SEPARATOR . $moduleId . "_" . time();
|
||||
if (!@rename($module->getBasePath(), $backupFolderName)) {
|
||||
throw new Exception("Could not remove module folder!" . $backupFolderName);
|
||||
throw new Exception("Could not move module to backup folder!" . $backupFolderName);
|
||||
}
|
||||
} else {
|
||||
//TODO: Delete directory
|
||||
}
|
||||
|
||||
|
||||
$this->flushCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables a module
|
||||
*
|
||||
* @since 1.1
|
||||
* @param \humhub\components\Module $module
|
||||
*/
|
||||
public function enable(Module $module)
|
||||
{
|
||||
$moduleEnabled = ModuleEnabled::findOne(['module_id' => $module->id]);
|
||||
if ($moduleEnabled == null) {
|
||||
$moduleEnabled = new ModuleEnabled();
|
||||
$moduleEnabled->module_id = $module->id;
|
||||
$moduleEnabled->save();
|
||||
}
|
||||
|
||||
$this->enabledModules[] = $module->id;
|
||||
$this->register($module->getBasePath());
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables a module
|
||||
*
|
||||
* @since 1.1
|
||||
* @param \humhub\components\Module $module
|
||||
*/
|
||||
public function disable(Module $module)
|
||||
{
|
||||
$moduleEnabled = ModuleEnabled::findOne(['module_id' => $module->id]);
|
||||
if ($moduleEnabled != null) {
|
||||
$moduleEnabled->delete();
|
||||
}
|
||||
|
||||
if (($key = array_search($module->id, $this->enabledModules)) !== false) {
|
||||
unset($this->enabledModules[$key]);
|
||||
}
|
||||
|
||||
Yii::$app->setModule($module->id, 'null');
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -12,8 +12,8 @@ use Yii;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* @author luke
|
||||
*/
|
||||
class Request extends \yii\web\Request
|
||||
@ -25,10 +25,10 @@ class Request extends \yii\web\Request
|
||||
public function init()
|
||||
{
|
||||
if (\humhub\models\Setting::isInstalled()) {
|
||||
$secret = \humhub\models\Setting::Get('secret');
|
||||
$secret = Yii::$app->settings->get('secret');
|
||||
if ($secret != "") {
|
||||
$this->cookieValidationKey = \humhub\models\Setting::Get('secret');
|
||||
}
|
||||
$this->cookieValidationKey = $secret;
|
||||
}
|
||||
} else {
|
||||
$this->cookieValidationKey = 'installer';
|
||||
}
|
||||
|
100
protected/humhub/components/SettingsManager.php
Normal file
100
protected/humhub/components/SettingsManager.php
Normal file
@ -0,0 +1,100 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\components;
|
||||
|
||||
use Yii;
|
||||
use humhub\libs\BaseSettingsManager;
|
||||
use humhub\modules\content\components\ContentContainerActiveRecord;
|
||||
use humhub\modules\content\components\ContentContainerSettingsManager;
|
||||
|
||||
/**
|
||||
* SettingsManager application component
|
||||
*
|
||||
* @since 1.1
|
||||
* @author Luke
|
||||
*/
|
||||
class SettingsManager extends BaseSettingsManager
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ContentContainerSettingsManager[] already loaded content container settings managers
|
||||
*/
|
||||
protected $contentContainers = [];
|
||||
|
||||
/**
|
||||
* Returns content container
|
||||
*
|
||||
* @param ContentContainerActiveRecord $container
|
||||
* @return ContentContainerSettingsManager
|
||||
*/
|
||||
public function contentContainer(ContentContainerActiveRecord $container)
|
||||
{
|
||||
if (isset($this->contentContainers[$container->id])) {
|
||||
return $this->contentContainers[$container->id];
|
||||
}
|
||||
|
||||
$this->contentContainers[$container->id] = new ContentContainerSettingsManager([
|
||||
'moduleId' => $this->moduleId,
|
||||
'contentContainer' => $container,
|
||||
]);
|
||||
|
||||
return $this->contentContainers[$container->id];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns ContentContainerSettingsManager for current logged in user
|
||||
* @return ContentContainerSettingsManager
|
||||
*/
|
||||
public function user()
|
||||
{
|
||||
return $this->contentContainer(Yii::$app->user->getIdentity());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns ContentContainerSettingsManager for current logged in user
|
||||
* @return ContentContainerSettingsManager
|
||||
*/
|
||||
public function space()
|
||||
{
|
||||
if (Yii::$app->controller instanceof \humhub\modules\content\components\ContentContainerController) {
|
||||
if (Yii::$app->controller->contentContainer instanceof \humhub\modules\space\models\Space) {
|
||||
return $this->contentContainer(Yii::$app->controller->contentContainer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates this setting is fixed in configuration file and cannot be
|
||||
* changed at runtime.
|
||||
*
|
||||
* @param string $name
|
||||
* @return boolean
|
||||
*/
|
||||
public function isFixed($name)
|
||||
{
|
||||
if (isset(Yii::$app->params['fixed-settings'][$this->moduleId][$name])) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
if ($this->isFixed($name)) {
|
||||
return Yii::$app->params['fixed-settings'][$this->moduleId][$name];
|
||||
}
|
||||
|
||||
return parent::get($name);
|
||||
}
|
||||
|
||||
}
|
124
protected/humhub/components/SocialActivity.php
Normal file
124
protected/humhub/components/SocialActivity.php
Normal file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\components;
|
||||
|
||||
use humhub\modules\notification\models\Notification;
|
||||
use humhub\modules\content\components\ContentActiveRecord;
|
||||
use humhub\modules\content\components\ContentContainerActiveRecord;
|
||||
use humhub\modules\content\components\ContentAddonActiveRecord;
|
||||
use humhub\libs\Viewable;
|
||||
|
||||
/**
|
||||
* Name (SocialEvent/NetworkEvent/SocialActivity/BaseEvent)
|
||||
*
|
||||
* This class represents an social activity triggered within the network.
|
||||
* An activity instance can be linked to an $originator user, which performed the activity.
|
||||
*
|
||||
* The activity mainly provides functions for rendering the output for different channels as
|
||||
* web, mail or plain-text.
|
||||
*
|
||||
* @since 1.1
|
||||
* @author buddha
|
||||
*/
|
||||
abstract class SocialActivity extends Viewable
|
||||
{
|
||||
|
||||
/**
|
||||
* User which performed the activity.
|
||||
*
|
||||
* @var \humhub\modules\user\models\User
|
||||
*/
|
||||
public $originator;
|
||||
|
||||
/**
|
||||
* The source instance which created this activity
|
||||
*
|
||||
* @var \yii\db\ActiveRecord
|
||||
*/
|
||||
public $source;
|
||||
|
||||
/**
|
||||
* The content container this activity belongs to.
|
||||
*
|
||||
* If the source object is a type of Content/ContentAddon or ContentContainer the container
|
||||
* will be automatically set.
|
||||
*
|
||||
* @var ContentContainerActiveRecord
|
||||
*/
|
||||
public $container = null;
|
||||
|
||||
/**
|
||||
* @var string the module id which this activity belongs to (required)
|
||||
*/
|
||||
public $moduleId = "";
|
||||
|
||||
/**
|
||||
* The notification record this notification belongs to
|
||||
*
|
||||
* @var Notification
|
||||
*/
|
||||
public $record;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
protected function getViewParams($params = [])
|
||||
{
|
||||
$params['originator'] = $this->originator;
|
||||
$params['source'] = $this->source;
|
||||
$params['contentContainer'] = $this->container;
|
||||
$params['record'] = $this->record;
|
||||
if (!isset($params['url'])) {
|
||||
$params['url'] = $this->getUrl();
|
||||
}
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Url of the origin of this notification
|
||||
* If source is a Content / ContentAddon / ContentContainer this will automatically generated.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getUrl()
|
||||
{
|
||||
$url = '#';
|
||||
|
||||
if ($this->source instanceof ContentActiveRecord || $this->source instanceof ContentAddonActiveRecord) {
|
||||
$url = $this->source->content->getUrl();
|
||||
} elseif ($this->source instanceof ContentContainerActiveRecord) {
|
||||
$url = $this->source->getUrl();
|
||||
}
|
||||
|
||||
// Create absolute URL, for E-Mails
|
||||
if (substr($url, 0, 4) !== 'http') {
|
||||
$url = \yii\helpers\Url::to($url, true);
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build info text about a content
|
||||
*
|
||||
* This is a combination a the type of the content with a short preview
|
||||
* of it.
|
||||
*
|
||||
* @param Content $content
|
||||
* @return string
|
||||
*/
|
||||
public function getContentInfo(\humhub\modules\content\interfaces\ContentTitlePreview $content)
|
||||
{
|
||||
return \yii\helpers\Html::encode($content->getContentName()) .
|
||||
' "' .
|
||||
\humhub\widgets\RichText::widget(['text' => $content->getContentDescription(), 'minimal' => true, 'maxLength' => 60]) . '"';
|
||||
}
|
||||
|
||||
}
|
@ -10,6 +10,7 @@ namespace humhub\components;
|
||||
|
||||
use Yii;
|
||||
use yii\helpers\FileHelper;
|
||||
use humhub\libs\ThemeHelper;
|
||||
use humhub\models\Setting;
|
||||
|
||||
/**
|
||||
@ -20,7 +21,7 @@ class Theme extends \yii\base\Theme
|
||||
|
||||
/**
|
||||
* Name of the Theme
|
||||
*
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $name;
|
||||
@ -30,6 +31,11 @@ class Theme extends \yii\base\Theme
|
||||
*/
|
||||
private $_baseUrl = null;
|
||||
|
||||
/**
|
||||
* Indicates that resources should be published via assetManager
|
||||
*/
|
||||
public $publishResources = false;
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
@ -46,26 +52,36 @@ class Theme extends \yii\base\Theme
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string the base URL (without ending slash) for this theme. All resources of this theme are considered
|
||||
* to be under this base URL.
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getBaseUrl()
|
||||
{
|
||||
|
||||
if ($this->_baseUrl !== null) {
|
||||
return $this->_baseUrl;
|
||||
}
|
||||
|
||||
$this->_baseUrl = rtrim(Yii::getAlias('@web/themes/' . $this->name), '/');
|
||||
$this->_baseUrl = ($this->publishResources) ? $this->publishResources() : rtrim(Yii::getAlias('@web/themes/' . $this->name), '/');
|
||||
return $this->_baseUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method will be called before when this theme is written to the
|
||||
* dynamic configuration file.
|
||||
*/
|
||||
public function beforeActivate()
|
||||
{
|
||||
// Force republish theme files
|
||||
$this->publishResources(true);
|
||||
|
||||
// Store color variables to configuration
|
||||
$this->storeColorsToConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function applyTo($path)
|
||||
{
|
||||
|
||||
$autoPath = $this->autoFindModuleView($path);
|
||||
if ($autoPath !== null && file_exists($autoPath)) {
|
||||
return $autoPath;
|
||||
@ -84,9 +100,28 @@ class Theme extends \yii\base\Theme
|
||||
return parent::applyTo($path);
|
||||
}
|
||||
|
||||
/**
|
||||
* Publishs theme assets (e.g. images or css)
|
||||
*
|
||||
* @param boolean|null $force
|
||||
* @return string url of published resources
|
||||
*/
|
||||
public function publishResources($force = null)
|
||||
{
|
||||
if ($force === null) {
|
||||
$force = (YII_DEBUG);
|
||||
}
|
||||
|
||||
$published = Yii::$app->assetManager->publish(
|
||||
$this->getBasePath(), ['forceCopy' => $force, 'except' => ['views/']]
|
||||
);
|
||||
|
||||
return $published[1];
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to automatically maps the view file of a module to a themed one.
|
||||
*
|
||||
*
|
||||
* Formats:
|
||||
|
||||
* .../moduleId/views/controllerId/viewName.php
|
||||
@ -96,7 +131,7 @@ class Theme extends \yii\base\Theme
|
||||
* .../moduleId/[widgets|activities|notifications]/views/viewName.php
|
||||
* to:
|
||||
* .../views/moduleId/[widgets|activities|notifications]/viewName.php
|
||||
*
|
||||
*
|
||||
* @return string theme view path or null
|
||||
*/
|
||||
protected function autoFindModuleView($path)
|
||||
@ -122,113 +157,13 @@ class Theme extends \yii\base\Theme
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of all installed themes.
|
||||
*
|
||||
* @return Array Theme instances
|
||||
* Stores color informations to configuration for use in modules.
|
||||
*/
|
||||
public static function getThemes()
|
||||
public function storeColorsToConfig()
|
||||
{
|
||||
$themes = array();
|
||||
$themePaths = [];
|
||||
$themePaths[] = \Yii::getAlias('@webroot/themes');
|
||||
|
||||
// Collect enabled module theme paths
|
||||
foreach (Yii::$app->getModules() as $module) {
|
||||
$basePath = "";
|
||||
if (is_array($module)) {
|
||||
if (isset($module['class'])) {
|
||||
$reflector = new \ReflectionClass($module['class']);
|
||||
$basePath = dirname($reflector->getFileName());
|
||||
}
|
||||
} else {
|
||||
$basePath = $module->getBasePath();
|
||||
}
|
||||
|
||||
if (is_dir($basePath . DIRECTORY_SEPARATOR . 'themes')) {
|
||||
$themePaths[] = $basePath . DIRECTORY_SEPARATOR . 'themes';
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($themePaths as $themePath) {
|
||||
foreach (scandir($themePath) as $file) {
|
||||
if ($file == "." || $file == ".." || !is_dir($themePath . DIRECTORY_SEPARATOR . $file)) {
|
||||
continue;
|
||||
}
|
||||
$themes[] = Yii::createObject([
|
||||
'class' => 'humhub\components\Theme',
|
||||
'basePath' => $themePath . DIRECTORY_SEPARATOR . $file,
|
||||
'name' => $file
|
||||
]);
|
||||
}
|
||||
}
|
||||
return $themes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Theme by given name
|
||||
*
|
||||
* @param string $name of the theme
|
||||
* @return Theme
|
||||
*/
|
||||
public static function getThemeByName($name)
|
||||
{
|
||||
foreach (self::getThemes() as $theme) {
|
||||
if ($theme->name === $name) {
|
||||
return $theme;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns configuration array of given theme
|
||||
*
|
||||
* @param Theme|string $theme name or theme instance
|
||||
* @return array Configuration
|
||||
*/
|
||||
public static function getThemeConfig($theme)
|
||||
{
|
||||
if (is_string($theme)) {
|
||||
$theme = self::getThemeByName($theme);
|
||||
}
|
||||
|
||||
if ($theme === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return [
|
||||
'components' => [
|
||||
'view' => [
|
||||
'theme' => [
|
||||
'name' => $theme->name,
|
||||
'basePath' => $theme->getBasePath()
|
||||
],
|
||||
],
|
||||
'mailer' => [
|
||||
'view' => [
|
||||
'theme' => [
|
||||
'name' => $theme->name,
|
||||
'basePath' => $theme->getBasePath()
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
public static function setColorVariables($themeName)
|
||||
{
|
||||
$theme = self::getThemeByName($themeName);
|
||||
|
||||
if ($theme === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$lessFileName = Yii::getAlias($theme->getBasePath() . '/css/theme.less');
|
||||
$lessFileName = $this->getBasePath() . '/css/theme.less';
|
||||
if (file_exists($lessFileName)) {
|
||||
$file = fopen($lessFileName, "r") or die("Unable to open file!");
|
||||
$less = fread($file, filesize($lessFileName));
|
||||
fclose($file);
|
||||
$less = file_get_contents($lessFileName);
|
||||
|
||||
$startDefault = strpos($less, '@default') + 10;
|
||||
$startPrimary = strpos($less, '@primary') + 10;
|
||||
@ -238,12 +173,27 @@ class Theme extends \yii\base\Theme
|
||||
$startDanger = strpos($less, '@danger') + 9;
|
||||
$length = 7;
|
||||
|
||||
Setting::Set('colorDefault', substr($less, $startDefault, $length));
|
||||
Setting::Set('colorPrimary', substr($less, $startPrimary, $length));
|
||||
Setting::Set('colorInfo', substr($less, $startInfo, $length));
|
||||
Setting::Set('colorSuccess', substr($less, $startSuccess, $length));
|
||||
Setting::Set('colorWarning', substr($less, $startWarning, $length));
|
||||
Setting::Set('colorDanger', substr($less, $startDanger, $length));
|
||||
Yii::$app->settings->set('colorDefault', substr($less, $startDefault, $length));
|
||||
Yii::$app->settings->set('colorPrimary', substr($less, $startPrimary, $length));
|
||||
Yii::$app->settings->set('colorInfo', substr($less, $startInfo, $length));
|
||||
Yii::$app->settings->set('colorSuccess', substr($less, $startSuccess, $length));
|
||||
Yii::$app->settings->set('colorWarning', substr($less, $startWarning, $length));
|
||||
Yii::$app->settings->set('colorDanger', substr($less, $startDanger, $length));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store colors to configuration.
|
||||
*
|
||||
* @deprecated since version 1.1
|
||||
* @param type $themeName
|
||||
*/
|
||||
public static function setColorVariables($themeName)
|
||||
{
|
||||
$theme = ThemeHelper::getThemeByName($themeName);
|
||||
|
||||
if ($theme !== null) {
|
||||
$theme->storeColorsToConfig();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -44,25 +44,26 @@ class AccessControl extends \yii\base\ActionFilter
|
||||
*/
|
||||
public function beforeAction($action)
|
||||
{
|
||||
|
||||
|
||||
$identity = Yii::$app->user->getIdentity();
|
||||
if($identity != null && !$identity->isActive()) {
|
||||
Yii::$app->user->logout();
|
||||
Yii::$app->response->redirect(Yii::$app->urlManager->createUrl('user/auth/login'));
|
||||
Yii::$app->response->redirect(['/user/auth/login']);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Yii::$app->user->isGuest) {
|
||||
if (!$this->loggedInOnly && !$this->adminOnly) {
|
||||
return true;
|
||||
}
|
||||
if (in_array($action->id, $this->guestAllowedActions) && Setting::Get('allowGuestAccess', 'authentication_internal') == 1) {
|
||||
if (in_array($action->id, $this->guestAllowedActions) && Yii::$app->getModule('user')->settings->get('auth.allowGuestAccess') == 1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Yii::$app->user->loginRequired();
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if ($this->adminOnly && !Yii::$app->user->isAdmin()) {
|
||||
$this->forbidden();
|
||||
}
|
||||
|
@ -38,8 +38,8 @@ class ModuleAutoLoader implements BootstrapInterface
|
||||
if (is_dir($moduleDir) && is_file($moduleDir . DIRECTORY_SEPARATOR . 'config.php')) {
|
||||
try {
|
||||
$modules[$moduleDir] = require($moduleDir . DIRECTORY_SEPARATOR . 'config.php');
|
||||
} catch (Exception $ex) {
|
||||
|
||||
} catch (\Exception $ex) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2015 HumHub GmbH & Co. KG
|
||||
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
@ -33,14 +33,20 @@ class Application extends \yii\console\Application
|
||||
$this->trigger(self::EVENT_ON_INIT);
|
||||
|
||||
if ($this->isDatabaseInstalled()) {
|
||||
$baseUrl = Setting::get('baseUrl');
|
||||
|
||||
if($baseUrl != null) {
|
||||
$baseUrl = Yii::$app->settings->get('baseUrl');
|
||||
if ($baseUrl !== null) {
|
||||
Yii::setAlias(("@web"), $baseUrl);
|
||||
$this->urlManager->scriptUrl = $baseUrl;
|
||||
$this->urlManager->baseUrl = $baseUrl;
|
||||
|
||||
// Set hostInfo based on given baseUrl
|
||||
$urlParts = parse_url($baseUrl);
|
||||
$hostInfo = $urlParts['scheme'] . '://' . $urlParts['host'];
|
||||
if (isset($urlParts['port'])) {
|
||||
$hostInfo .= ':' . $urlParts['port'];
|
||||
}
|
||||
$this->urlManager->hostInfo = $hostInfo;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -60,7 +66,7 @@ class Application extends \yii\console\Application
|
||||
|
||||
/**
|
||||
* Checks if database is installed
|
||||
*
|
||||
*
|
||||
* @return boolean is database installed/migrated
|
||||
*/
|
||||
public function isDatabaseInstalled()
|
||||
@ -68,7 +74,7 @@ class Application extends \yii\console\Application
|
||||
if (in_array('setting', Yii::$app->db->schema->getTableNames())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
namespace humhub\components\i18n;
|
||||
|
||||
use Yii;
|
||||
use humhub\models\Setting;
|
||||
|
||||
/**
|
||||
@ -20,7 +21,7 @@ class Formatter extends \yii\i18n\Formatter
|
||||
* @inheritdoc
|
||||
*/
|
||||
public $sizeFormatBase = 1000;
|
||||
|
||||
|
||||
/**
|
||||
* @var string the default format string to be used to format a input field [[asDate()|date]].
|
||||
* This mostly used in forms (DatePicker).
|
||||
@ -35,8 +36,8 @@ class Formatter extends \yii\i18n\Formatter
|
||||
{
|
||||
parent::init();
|
||||
|
||||
if (Setting::Get('defaultDateInputFormat', 'admin') != '') {
|
||||
$this->dateInputFormat = Setting::Get('defaultDateInputFormat', 'admin');
|
||||
if (Yii::$app->getModule('admin')->settings->get('defaultDateInputFormat') != '') {
|
||||
$this->dateInputFormat = Yii::$app->getModule('admin')->settings->get('defaultDateInputFormat');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ Yii::setAlias('@config', '@app/config');
|
||||
|
||||
$config = [
|
||||
'name' => 'HumHub',
|
||||
'version' => '1.1.0-dev',
|
||||
'version' => '1.2.0-dev',
|
||||
'basePath' => dirname(__DIR__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR,
|
||||
'bootstrap' => ['log', 'humhub\components\bootstrap\ModuleAutoLoader'],
|
||||
'sourceLanguage' => 'en',
|
||||
@ -27,6 +27,7 @@ $config = [
|
||||
[
|
||||
'class' => 'yii\log\DbTarget',
|
||||
'levels' => ['error', 'warning'],
|
||||
'except' => ['yii\web\HttpException:404'],
|
||||
'logVars' => ['_GET', '_SERVER'],
|
||||
],
|
||||
],
|
||||
@ -34,6 +35,10 @@ $config = [
|
||||
'search' => array(
|
||||
'class' => 'humhub\modules\search\engine\ZendLuceneSearch',
|
||||
),
|
||||
'settings' => array(
|
||||
'class' => 'humhub\components\SettingsManager',
|
||||
'moduleId' => 'base',
|
||||
),
|
||||
'i18n' => [
|
||||
'class' => 'humhub\components\i18n\I18N',
|
||||
'translations' => [
|
||||
@ -53,10 +58,6 @@ $config = [
|
||||
'class' => 'yii\i18n\PhpMessageSource',
|
||||
'basePath' => '@humhub/messages'
|
||||
],
|
||||
'iso3166Codes' => [
|
||||
'class' => 'yii\i18n\PhpMessageSource',
|
||||
'basePath' => '@humhub/messages'
|
||||
],
|
||||
],
|
||||
],
|
||||
'formatter' => [
|
||||
|
@ -5,7 +5,7 @@ return [
|
||||
'sourcePath' => __DIR__ . DIRECTORY_SEPARATOR . '..',
|
||||
// array, required, list of language codes that the extracted messages
|
||||
// should be translated to. For example, ['zh-CN', 'de'].
|
||||
'languages' => array('de', 'fr', 'nl', 'pt', 'pl', 'pt_br', 'es', 'it', 'tr', 'ru', 'th', 'uk', 'el', 'hu', 'ja', 'nb_no', 'zh_cn', 'ca', 'an', 'cs', 'vi', 'sv', 'da', 'uz', 'fa_ir', 'bg', 'sk', 'en_uk', 'zh_tw', 'ro', 'ar', 'id', 'ko', 'lt', 'hr'),
|
||||
'languages' => array('de', 'fr', 'nl', 'pt', 'pl', 'pt_br', 'es', 'it', 'tr', 'ru', 'th', 'uk', 'el', 'hu', 'ja', 'nb_no', 'zh_cn', 'ca', 'an', 'cs', 'vi', 'sv', 'da', 'uz', 'fa_ir', 'bg', 'sk', 'zh_tw', 'ro', 'ar', 'id', 'ko', 'lt', 'hr'),
|
||||
// string, the name of the function for translating messages.
|
||||
// Defaults to 'Yii::t'. This is used as a mark to find the messages to be
|
||||
// translated. You may use a string for single function name or an array for
|
||||
|
@ -49,7 +49,7 @@ class ErrorController extends Controller
|
||||
/**
|
||||
* Show special login required view for guests
|
||||
*/
|
||||
if (Yii::$app->user->isGuest && $exception instanceof HttpException && $exception->statusCode == "401" && Setting::Get('allowGuestAccess', 'authentication_internal')) {
|
||||
if (Yii::$app->user->isGuest && $exception instanceof HttpException && $exception->statusCode == "401" && Yii::$app->getModule('user')->settings->get('auth.allowGuestAccess')) {
|
||||
return $this->render('@humhub/views/error/401_guests', ['message' => $message]);
|
||||
}
|
||||
|
||||
|
@ -5,18 +5,20 @@ Introduction
|
||||
------------
|
||||
* [About HumHub](intro-index.md)
|
||||
* [Licence](intro-licence.md)
|
||||
* [Bundled Software](intro-bundled_software.md)
|
||||
|
||||
Administration
|
||||
Getting Started
|
||||
---------------
|
||||
|
||||
* [Requirements](admin-requirements.md)
|
||||
* [Installation](admin-installation.md)
|
||||
* [Updating](admin-updating.md)
|
||||
|
||||
Administration
|
||||
---------------------
|
||||
* [User](admin-user.md)
|
||||
* [Spaces](admin-spaces.md)
|
||||
|
||||
Administration - Topics
|
||||
-------------------------
|
||||
* [Authentication](admin-authentication.md)
|
||||
* [Advanced Configuration](admin-adv-config.md)
|
||||
* [Console](admin-adv-console.md)
|
||||
* [Search](admin-adv-search.md)
|
||||
@ -27,34 +29,22 @@ Development
|
||||
---------------------
|
||||
|
||||
* [Getting Started](dev-index.md)
|
||||
* [Updating / Migrate](dev-migrate.md)
|
||||
* [Application Overview](dev-overview.md)
|
||||
* [Update / Migration](dev-migrate.md)
|
||||
* [Content](dev-content.md)
|
||||
* [Notification](dev-notifications.md)
|
||||
* [Activities](dev-environment.md)
|
||||
* [Search](dev-environment.md)
|
||||
* [User](dev-environment.md)
|
||||
* [Build](dev-environment.md)
|
||||
* [Frontend](dev-javascript.md)
|
||||
* [Contributions](dev-contributing.md)
|
||||
|
||||
|
||||
Development - Modules
|
||||
---------------------
|
||||
|
||||
* [Getting Started](dev-module-index.md)
|
||||
* [Events](dev-module-events.md)
|
||||
* [Database](dev-module-db.md)
|
||||
* [Space/User](dev-module-spaceuser.md)
|
||||
* [Navigations](dev-module-menus.md)
|
||||
* [Widget Stacks](dev-module-stack.md)
|
||||
* [Activities](dev-module-activities.md)
|
||||
* [Streams / Walls](dev-module-stream.md)
|
||||
* [Search](dev-module-search.md)
|
||||
* [Translations](dev-module-i18n.md)
|
||||
* [CronJobs](dev-module-cron.md)
|
||||
* [Console](dev-module-console.md)
|
||||
* [Special Topics](dev-module-special-topics.md)
|
||||
* [Permissions](dev-permissions.md)
|
||||
* [Notifications](dev-notifications.md)
|
||||
* [Activities](dev-activities.md)
|
||||
* [Streams](dev-stream.md)
|
||||
* [Events](dev-events.md)
|
||||
* [Widgets](dev-widgets.md)
|
||||
* [Internationalization](dev-i18n.md)
|
||||
* [Authentication](dev-authentication.md)
|
||||
* [Models / Database](dev-db.md)
|
||||
* [Search](dev-search.md)
|
||||
* [CronJobs](dev-cron.md)
|
||||
* [Settings and Configuration](dev-settings.md)
|
||||
* [Console Application](dev-console.md)
|
||||
* [Module Development](dev-module.md)
|
||||
|
||||
Theming
|
||||
-------
|
||||
@ -62,10 +52,3 @@ Theming
|
||||
* [Getting Started](theming-index.md)
|
||||
* [Update / Migrate](theming-migrate.md)
|
||||
|
||||
|
||||
Special Topics
|
||||
--------------
|
||||
|
||||
* [Translations](special-translations.md)
|
||||
* [Bundled Software](special-bundled_software.md)
|
||||
|
||||
|
@ -1,72 +0,0 @@
|
||||
Authentication
|
||||
==============
|
||||
|
||||
## Example: GitHub Authentication
|
||||
|
||||
- Obtain Application ID and Secret from GitHub
|
||||
- Add following block to protected/config/common.php
|
||||
|
||||
```
|
||||
// ...
|
||||
'components' => [
|
||||
// ...
|
||||
'authClientCollection' => [
|
||||
'class' => 'yii\authclient\Collection',
|
||||
'clients' => [
|
||||
'github' => [
|
||||
'class' => 'yii\authclient\clients\GitHub',
|
||||
'clientId' => '--->your-client-id<---',
|
||||
'clientSecret' => '--->your-client-secret<---',
|
||||
'normalizeUserAttributeMap' => [
|
||||
'username' => 'login',
|
||||
'firstname' => function ($attributes) {
|
||||
list($f, $l) = mb_split(' ', $attributes['name'], 2);
|
||||
return $f;
|
||||
},
|
||||
'lastname' => function ($attributes) {
|
||||
list($f, $l) = mb_split(' ', $attributes['name'], 2);
|
||||
return $l;
|
||||
},
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
// ..
|
||||
],
|
||||
// ...
|
||||
```
|
||||
|
||||
## Example: Facebook
|
||||
|
||||
- Obtain Application ID and Secret from Facebook
|
||||
- Add following block to protected/config/common.php
|
||||
|
||||
```
|
||||
// ...
|
||||
'components' => [
|
||||
// ...
|
||||
'authClientCollection' => [
|
||||
'class' => 'yii\authclient\Collection',
|
||||
'clients' => [
|
||||
'facebook' => [
|
||||
'class' => 'yii\authclient\clients\Facebook',
|
||||
'clientId' => '1662633133992750',
|
||||
'clientSecret' => '3c786f625a26f7f3649bd5cc8d8c6a61',
|
||||
'normalizeUserAttributeMap' => [
|
||||
'username' => 'name',
|
||||
'firstname' => function ($attributes) {
|
||||
list($f, $l) = mb_split(' ', $attributes['name'], 2);
|
||||
return $f;
|
||||
},
|
||||
'lastname' => function ($attributes) {
|
||||
list($f, $l) = mb_split(' ', $attributes['name'], 2);
|
||||
return $l;
|
||||
},
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
// ..
|
||||
],
|
||||
// ...
|
||||
```
|
@ -66,7 +66,7 @@ config/messages/de/PostModule.widgets_views_postForm.php
|
||||
|
||||
with the content:
|
||||
|
||||
``` php
|
||||
```php
|
||||
<?php
|
||||
return array (
|
||||
'What\'s on your mind?' => 'Wie geht es dir heute?',
|
||||
|
140
protected/humhub/docs/guide/admin-authentication.md
Normal file
140
protected/humhub/docs/guide/admin-authentication.md
Normal file
@ -0,0 +1,140 @@
|
||||
Authentication
|
||||
==============
|
||||
|
||||
LDAP
|
||||
----
|
||||
|
||||
You can enable authentication against LDAP (e.g. against Active Directory or OpenLDAP) via
|
||||
`Administration -> Settings -> User -> LDAP`.
|
||||
|
||||
Facebook
|
||||
--------
|
||||
|
||||
In order to use Facebook OAuth you must register your application at <https://developers.facebook.com/apps>.
|
||||
|
||||
Add following block to your configuration (protected/config/common.php):
|
||||
|
||||
```php
|
||||
return [
|
||||
// ...
|
||||
'components' => [
|
||||
// ...
|
||||
'authClientCollection' => [
|
||||
'clients' => [
|
||||
// ...
|
||||
'facebook' => [
|
||||
'class' => 'humhub\modules\user\authclient\Facebook',
|
||||
'clientId' => 'Your Facebook App ID here',
|
||||
'clientSecret' => 'Your Facebook App 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>.
|
||||
|
||||
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>.
|
||||
|
||||
Add following block to your configuration (protected/config/common.php):
|
||||
|
||||
```php
|
||||
return [
|
||||
// ...
|
||||
'components' => [
|
||||
// ...
|
||||
'authClientCollection' => [
|
||||
'clients' => [
|
||||
// ...
|
||||
'google' => [
|
||||
'class' => 'humhub\modules\user\authclient\Google',
|
||||
'clientId' => 'Your Client ID here',
|
||||
'clientSecret' => 'Your Client Secret here',
|
||||
],
|
||||
],
|
||||
],
|
||||
// ...
|
||||
],
|
||||
// ...
|
||||
];
|
||||
```
|
||||
|
||||
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):
|
||||
|
||||
```php
|
||||
return [
|
||||
// ...
|
||||
'components' => [
|
||||
// ...
|
||||
'authClientCollection' => [
|
||||
'clients' => [
|
||||
// ...
|
||||
'github' => [
|
||||
'class' => 'humhub\modules\user\authclient\GitHub',
|
||||
'clientId' => 'Your GitHub Client ID here',
|
||||
'clientSecret' => 'Your GitHub Client Secret here',
|
||||
],
|
||||
],
|
||||
],
|
||||
// ...
|
||||
],
|
||||
// ...
|
||||
];
|
||||
```
|
||||
|
||||
|
||||
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.
|
||||
|
||||
- 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):
|
||||
|
||||
```php
|
||||
return [
|
||||
// ...
|
||||
'components' => [
|
||||
// ...
|
||||
'authClientCollection' => [
|
||||
'clients' => [
|
||||
// ...
|
||||
'live' => [
|
||||
'class' => 'humhub\modules\user\authclient\Live',
|
||||
'clientId' => 'Your Microsoft application ID here',
|
||||
'clientSecret' => 'Your Microsoft application password here',
|
||||
],
|
||||
],
|
||||
],
|
||||
// ...
|
||||
],
|
||||
// ...
|
||||
];
|
||||
```
|
||||
|
||||
Other providers
|
||||
---------------
|
||||
|
||||
Please see [Development - Authentication](dev-authentication.md) for more information
|
||||
about additional authentication providers.
|
@ -1,7 +1,7 @@
|
||||
Installation
|
||||
============
|
||||
|
||||
## 1. Preparation
|
||||
## Preparation
|
||||
|
||||
Create an MySQL Database, e.g.:
|
||||
|
||||
@ -11,16 +11,31 @@ GRANT ALL ON `humhub`.* TO `humhub_dbuser`@localhost IDENTIFIED BY 'password_cha
|
||||
FLUSH PRIVILEGES;
|
||||
```
|
||||
|
||||
## 2. Get HumHub
|
||||
> Note: Do not forget to change the `humhub_dbuser` and `password_changeme`!
|
||||
|
||||
## Get HumHub
|
||||
|
||||
### Via: Download Package
|
||||
|
||||
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).
|
||||
After the download is completed, just extract the package into the htdocs folder of your webserver.
|
||||
|
||||
### Via: Git/Composer
|
||||
|
||||
To be able to install a branch retrieved by git you'll have to run a composer update to download all external dependencies.
|
||||
|
||||
- Clone Git Repository
|
||||
|
||||
```
|
||||
git clone https://github.com/humhub/humhub.git
|
||||
```
|
||||
|
||||
- Switch to stable branch (recommended)
|
||||
|
||||
```
|
||||
git checkout stable
|
||||
```
|
||||
|
||||
- Install composer ([https://getcomposer.org/doc/00-intro.md](https://getcomposer.org/doc/00-intro.md))
|
||||
- Navigate to your HumHub webroot and fetch dependencies
|
||||
|
||||
@ -29,11 +44,9 @@ php composer.phar global require "fxp/composer-asset-plugin:~1.1.1"
|
||||
composer update
|
||||
```
|
||||
|
||||
### Via: Download Package
|
||||
> 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](http://localhost/codebase/doku/guide-admin-updating.html#gitcomposer-based-installations))
|
||||
|
||||
Download package at [http://www.humhub.org/downloads](http://www.humhub.org/downloads) and extract it somewhere into your htdocs folder.
|
||||
|
||||
## 3. Setting up
|
||||
## Setting up
|
||||
|
||||
### File Modes / Permissions
|
||||
|
||||
@ -48,19 +61,26 @@ Make the following files executable:
|
||||
- /protected/yii
|
||||
- /protected/yii.bat
|
||||
|
||||
**Make sure following directories are not accessible throu webserver!**
|
||||
|
||||
(These folders are protected by default with ".htaccess")
|
||||
|
||||
- protected
|
||||
- uploads/file
|
||||
|
||||
### Start Installer
|
||||
|
||||
Open installation in your browser (e.g. [http://localhost/humhub](http://localhost/humhub))
|
||||
|
||||
|
||||
## 4. Fine Tuning
|
||||
## Fine Tuning
|
||||
|
||||
### E-Mail Configuration
|
||||
|
||||
Depending on your environment which you are using you may want specify a local or remote SMTP Server.
|
||||
You can change this settings at `Administration -> Mailing -> Server Settings`.
|
||||
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 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>
|
||||
|
||||
|
||||
### Enable Url Rewriting (Optional)
|
||||
@ -84,11 +104,8 @@ return [
|
||||
|
||||
### Enable Cron Jobs
|
||||
|
||||
Daily cron command:
|
||||
> yii cron/daily
|
||||
|
||||
Hourly cron command:
|
||||
> yii cron/hourly
|
||||
- Daily cron command: `> yii cron/daily`
|
||||
- Hourly cron command: `> yii cron/hourly`
|
||||
|
||||
Example Tab:
|
||||
|
||||
@ -97,15 +114,6 @@ Example Tab:
|
||||
00 18 * * * /path/to/humhub/protected/yii cron/daily >/dev/null 2>&1
|
||||
```
|
||||
|
||||
### Check Directory Protection
|
||||
|
||||
**Make sure following directories are not accessible throu webserver!**
|
||||
|
||||
(These folders are protected by default with ".htaccess")
|
||||
|
||||
- protected
|
||||
- uploads/file
|
||||
|
||||
### Disable Errors / Debugging
|
||||
|
||||
- Modify *index.php* in humhub root directory
|
||||
|
@ -7,7 +7,7 @@ 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_.
|
||||
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.
|
||||
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.
|
||||
|
@ -1,14 +1,16 @@
|
||||
Updating
|
||||
========
|
||||
|
||||
> Warning: Before you run an update please check, if your installed modules and themes are compatible with your target version. If not, you can follow the migration guides.
|
||||
- [Theme Migration Guide](theming-migrate.md)
|
||||
- [Module Migration Guide](dev-migrate.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")**
|
||||
|
||||
1. Before you run an update please check, if your installed modules and themes are compatible with your target 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.
|
||||
|
||||
2. Backup your data:
|
||||
- Backup the whole HumHub installation folder from your webroot
|
||||
- Make a complete MySQL Backup from your HumHub database
|
||||
> NOTE: Backup your data:
|
||||
- Backup the whole HumHub installation folder from your webroot
|
||||
- Make a complete MySQL Backup from your HumHub database
|
||||
|
||||
|
||||
## Download Package installations
|
||||
|
@ -2,7 +2,7 @@ User
|
||||
=======
|
||||
##User Management
|
||||
|
||||
Users can be managed under _Administration -> Users_.
|
||||
Users are managed under **Administration -> Users**.
|
||||
|
||||
###Overview:
|
||||
|
||||
@ -12,54 +12,43 @@ The _Overview_ lists all registrated users with actions to
|
||||
- _Edit User_
|
||||
- _Delete User_
|
||||
|
||||
###Add new user:
|
||||
> Note: You can only delete users which are not owner of a space. You'll have to assign a new space-owner in the space-settings before beeing able to delte the user account.
|
||||
|
||||
Beside the registration of new users, users can be added by system administrators under _Administration -> Add new user_.
|
||||
###Add new users:
|
||||
|
||||
###Login As User:
|
||||
Beside the registration of a new user, users can be added by system administrators under _Administration -> Users -> Add new user_.
|
||||
|
||||
Administrators are able to login as another user by clicking on _Become this user_ on the bottom of the user edit form.
|
||||
###Login as a specific User:
|
||||
|
||||
Administrators are able to login as other users by clicking on **Become this user** within the user edit view.
|
||||
|
||||
## Authentication
|
||||
|
||||
The way users can register to the system can be configured under _Administration -> Authentication_.
|
||||
The way users can be registered to your HumHub instance is configurable under **Administration -> Authentication**.
|
||||
The following configurations are available:
|
||||
|
||||
**Allow limited access for non-authenticated user (guests):**
|
||||
|
||||
- **Allow limited access for non-authenticated user (guests)**:
|
||||
Guest users are non-authenticated users and are able to view public accessible content if this option is enabled.
|
||||
Instead of showing an initial Login modal, non-authenticated users are able to access the directory and dashboard and view public content of spaces.
|
||||
|
||||
**Anonymous users can register:**
|
||||
|
||||
- **Anonymous users can register:**
|
||||
If this checkbox is enabled anonymous users will be able to send registration requests to the system.
|
||||
|
||||
**Members can invite external users by email:**
|
||||
|
||||
- **Members can invite external users by email**:
|
||||
If this checkbox is enabled all members will be able to invite new users by email.
|
||||
|
||||
**Require group admin approval after registration:**
|
||||
|
||||
- **Require group admin approval after registration**:
|
||||
This checkbox will either add an additional group dropdown selection to the registration form,
|
||||
or automatically add the user to a default group. After the registration, all admins of the given group will be informed about a new pending user request
|
||||
and have the possibility to accept or decline the registration request.
|
||||
|
||||
**Default user group for new users:**
|
||||
|
||||
- **Default user group for new users**:
|
||||
With this selection you can set the default group for all new users. If 'None' is selected the user will be able to
|
||||
select an group while registration (If the group admin approval is activated).
|
||||
|
||||
**Default user idle timeout, auto-logout (in seconds, optional)**
|
||||
|
||||
- **Default user idle timeout, auto-logout (in seconds, optional):**
|
||||
Sets the time in seconds before inactive users session is closed, min value 20 seconds, default 1400seconds/24minutes.
|
||||
|
||||
**Default user profile visiblity**
|
||||
|
||||
- **Default user profile visiblity**:
|
||||
Sets the default visibility of user profiles. This is only applicable when limited access for non-authenticated users is enabled.
|
||||
Changes of this selection will only affect new users. It can either be set to _members only_ or _members and guests_.
|
||||
|
||||
##User Approval
|
||||
|
||||
Pending users can either be approved by group admins over the _Dashboard_ and _Account Dropdown -> User Approval_ or by System Admins under _Administration -> User Approval_.
|
||||
|
||||
Pending users can either be approved by group managers under the **Dashboard/Account Dropdown -> User Approval** or by Administrators under **Administration -> User Approval**.
|
||||
|
||||
> Note: The approval process is only needed if the **Require group admin approval after registration** checkbox within the user authentication settings is enabled.
|
||||
|
72
protected/humhub/docs/guide/dev-activities.md
Normal file
72
protected/humhub/docs/guide/dev-activities.md
Normal file
@ -0,0 +1,72 @@
|
||||
Activities
|
||||
==========
|
||||
|
||||
An activity is instance is created for special events in the context of a [[humhub\modules\content\models\ContentContainer|ContentContainer]] as the creation of new content.
|
||||
|
||||
Contrary to notifications - activities are always bound to a [[humhub\modules\content\models\ContentContainer|ContentContainer]], so they are not especially linked against a user or a given set of them.
|
||||
Besides the link to the [[humhub\modules\content\models\ContentContainer|ContentContainer]] - an activity can also be assigned with a Content or ContentAddon. So it will automatically inherit some content attributes such as visiblity.
|
||||
|
||||
> Note: Internally activities are handled as content.
|
||||
|
||||
## Implement a Custom Activity
|
||||
|
||||
### Create Class & View
|
||||
|
||||
Create a folder ** activities ** in your module and a new class ** SomethingHappend **
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace johndoe\example\activities;
|
||||
|
||||
use humhub\core\activity\components\BaseActivity;
|
||||
|
||||
/**
|
||||
* Notifies a user about something happend
|
||||
*/
|
||||
class SomethingHappend extends BaseActivity
|
||||
{
|
||||
// View Name for activity
|
||||
public $viewName = "somethingHappend";
|
||||
|
||||
// Module Id (required)
|
||||
public $moduleId = "example";
|
||||
}
|
||||
?>
|
||||
```
|
||||
|
||||
By default activity views should be located inside a subfolder named ** views ** where your activity class is located. (e.g. /modules/examples/activities/views/)
|
||||
|
||||
Example view file ** somethingHappend.php **:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use yii\helpers\Html;
|
||||
|
||||
echo Yii::t('ExampleModule.views_notifications_newLike', "%someUser% did something cool.", array(
|
||||
'%someUser%' => '<strong>' . Html::encode($originator->displayName) . '</strong>'
|
||||
));
|
||||
?>
|
||||
```
|
||||
|
||||
If you require a different view for mails. You can create a ** mail ** folder in your views directory.
|
||||
|
||||
### Persist an Activity
|
||||
|
||||
```php
|
||||
$activity = new \johndoe\example\activities\NewLike();
|
||||
|
||||
// Link to a ContentContainer, Content or ContentAddon
|
||||
$activity->source = $this;
|
||||
|
||||
// User which trigged this Activity - in case of Content/ContentAddon the Creator will be automatically set.
|
||||
$activity->originator = $user;
|
||||
|
||||
$activity->create();
|
||||
```
|
||||
|
||||
|
||||
### Delete
|
||||
|
||||
TBD
|
41
protected/humhub/docs/guide/dev-authentication.md
Normal file
41
protected/humhub/docs/guide/dev-authentication.md
Normal file
@ -0,0 +1,41 @@
|
||||
Authentication
|
||||
===============
|
||||
|
||||
HumHub is using <http://www.yiiframework.com/doc-2.0/ext-authclient-index.html> to provide an interface to pluggable authentication providers.
|
||||
|
||||
|
||||
Implementing own AuthClients
|
||||
----------------------------
|
||||
|
||||
Please see <https://github.com/yiisoft/yii2-authclient/blob/master/docs/guide/README.md> for more details.
|
||||
|
||||
|
||||
HumHub Specific Extensions
|
||||
--------------------------
|
||||
|
||||
Optionally your custom client can implement following interfaces to provide additional HumHub features.
|
||||
|
||||
### ApprovalBypass
|
||||
|
||||
Use interface ([[humhub\modules\user\authclient\interfaces\ApprovalBypass]]) to skip user approval for new users.
|
||||
|
||||
### AutoSyncUsers
|
||||
|
||||
The interface ([[humhub\modules\user\authclient\interfaces\AutoSyncUsers]]) the HumHub cronjob will execute
|
||||
the AuthClients syncUsers method hourly to create, update or delete existing users.
|
||||
|
||||
### SyncAttributes
|
||||
|
||||
By using the interface ([[humhub\modules\user\authclient\interfaces\SyncAttributes]]) interface - you can define user attribute (e.g. profile fields) to
|
||||
be automatically updated by the AuthClient and cannot be changed by the user.
|
||||
|
||||
### PrimaryClient
|
||||
|
||||
A user can only belongs to one ([[humhub\modules\user\authclient\interfaces\PrimaryClient]]) AuthClient.
|
||||
|
||||
Example for PrimaryClients:
|
||||
|
||||
- Standard Password Authentication
|
||||
- LDAP
|
||||
|
||||
|
3
protected/humhub/docs/guide/dev-build.md
Normal file
3
protected/humhub/docs/guide/dev-build.md
Normal file
@ -0,0 +1,3 @@
|
||||
Build
|
||||
========
|
||||
(TBD)
|
61
protected/humhub/docs/guide/dev-console.md
Normal file
61
protected/humhub/docs/guide/dev-console.md
Normal file
@ -0,0 +1,61 @@
|
||||
Console Application
|
||||
=====================
|
||||
|
||||
## Add controller to the console application
|
||||
|
||||
To add a custom controller to the console application, you need to catch the [[humhub\components\console\Application::EVENT_ON_INIT]].
|
||||
|
||||
|
||||
Example event:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use humhub\components\console\Application;
|
||||
|
||||
return [
|
||||
'id' => 'translation',
|
||||
'class' => 'humhub\modules\translation\Module',
|
||||
'namespace' => 'humhub\modules\translation',
|
||||
'events' => array(
|
||||
//...
|
||||
array('class' => Application::className(), 'event' => Application::EVENT_ON_INIT, 'callback' => array('humhub\modules\translation\Module', 'onConsoleApplicationInit')),
|
||||
//...
|
||||
),
|
||||
];
|
||||
?>
|
||||
```
|
||||
|
||||
Example callback:
|
||||
|
||||
```php
|
||||
public static function onConsoleApplicationInit($event) {
|
||||
$application = $event->sender;
|
||||
$application->controllerMap['translation'] = commands\TranslationController::className();
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Integrity Checker
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
@ -3,8 +3,9 @@ Content
|
||||
|
||||
## ContentContainer
|
||||
|
||||
A [[humhub\modules\content\models\ContentContainer|ContentContainer]] in HumHub is the base concept for assigning content to a specific container instance.
|
||||
A [[humhub\modules\content\models\ContentContainer|ContentContainer]] is assigned with a unique guid, which is used in controllers to identify the context of its actions.
|
||||
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]]
|
||||
@ -16,8 +17,8 @@ Currently there are two types of ContentContainer:
|
||||
|
||||
### ContentContainerController
|
||||
|
||||
The [[humhub\modules\content\components\ContentContainerController|ContentContainerController]] class should be extended by controllers, which are working in the context of a [[humhub\modules\content\models\ContentContainer|ContentContainer]].
|
||||
A [[humhub\modules\content\components\ContentContainerController|ContentContainerController]] will automatically search a **sguid** (Space) or **uguid** (User) request parameter for every request and will instantiate the associated [[humhub\modules\content\models\ContentContainer|ContentContainer]].
|
||||
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 a **sguid** (Space) or **uguid** (User) request parameter for every request and will instantiate and provide the associated [[humhub\modules\content\models\ContentContainer|ContentContainer]].
|
||||
|
||||
The [[humhub\modules\content\components\ContentContainerController|ContentContainerController]] provides common tasks like:
|
||||
|
||||
@ -26,7 +27,7 @@ The [[humhub\modules\content\components\ContentContainerController|ContentContai
|
||||
- Layout selection based on container type (User or Space)
|
||||
- Create URL's for the given ContentContainer
|
||||
|
||||
For example,
|
||||
For example:
|
||||
|
||||
```php
|
||||
class ExampleController extends \humhub\modules\content\components\ContentContainerController
|
||||
@ -57,19 +58,26 @@ Links to a [[humhub\modules\content\components\ContentContainerController|Conten
|
||||
Each ContentContainer class is derived from [[\humhub\modules\content\components\ContentContainerActiveRecord]].
|
||||
Beside others, this abstract class provides the following functionality:
|
||||
|
||||
- Permission Management
|
||||
- Getter for Profile-/BannerImage
|
||||
- [Permission Management](dev-permissions.md) `getPermissionManager()`
|
||||
- Profile-/Banner-image access `getProfileImage()`, `getProfileBannerImage()`
|
||||
- Rendering the container stream `getWallOut()` (see [Permission Management](dev-stream.md))
|
||||
|
||||
TBD (URL, AccessChecking, ProfileImage)
|
||||
Profile image example:
|
||||
|
||||
```php
|
||||
//Get Profile Image Url
|
||||
$profileImage = $space->getProfileImage();
|
||||
if($profileImage->hasImage()) {
|
||||
$url = $profileImage->getUrl();
|
||||
}
|
||||
```
|
||||
|
||||
### ContentContainerModule
|
||||
|
||||
If a module should be shown in the content containers module section, the module class must extend [[humhub\modules\content\components\ContentContainerModule]].
|
||||
If a module should appear in the content containers module section, the module class must extend [[humhub\modules\content\components\ContentContainerModule]].
|
||||
A ContentContainerModule can be enabled or disabled for a specific ContentContainer. The calendar module, for example, can be enabled for a specific space or a specific user account.
|
||||
|
||||
If you're working with content or other persistent data, make also sure to delete it when the module is disabled on a content container. Do this by overwriting the method [[humhub\modules\content\components\ContentContainerModule::disableContentContainer]].
|
||||
|
||||
See [[humhub\modules\content\components\ContentContainerModule]] class for a full list of options.
|
||||
See the [[humhub\modules\content\components\ContentContainerModule]] class for a full list of options.
|
||||
|
||||
Example of a modules `Module.php` file:
|
||||
|
||||
@ -77,27 +85,31 @@ Example of a modules `Module.php` file:
|
||||
class Module extends \humhub\modules\content\components\ContentContainerModule
|
||||
{
|
||||
|
||||
// Defines for which content container type this module is appropriate
|
||||
public function getContentContainerTypes()
|
||||
{
|
||||
//This content container can be assigned to Spaces and User
|
||||
// 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) {
|
||||
@ -107,20 +119,8 @@ class Module extends \humhub\modules\content\components\ContentContainerModule
|
||||
}
|
||||
}
|
||||
```
|
||||
> Note: If you're working with content or other persistent data, make sure to delete the container related data, when the module is disabled on a content container. This can be archieved by overwriting the [[humhub\modules\content\components\ContentContainerModule::disableContentContainer]] method.
|
||||
|
||||
### ContentContainerPermissionManager
|
||||
|
||||
Beside permissions for groups, you can assign permissions to a ContentContainer.
|
||||
|
||||
(TBD link to permissions docs)
|
||||
|
||||
### ContentContainerPermission
|
||||
|
||||
(TBD)
|
||||
|
||||
### ContentContainerStream
|
||||
|
||||
(TBD)
|
||||
|
||||
## Content
|
||||
|
||||
@ -138,10 +138,10 @@ This Content record holds all neccessary informations and provides common method
|
||||
- Archiving / Sticking
|
||||
- And more...
|
||||
|
||||
If you're implementing an ActiveRecord based on [[humhub\modules\content\components\ContentContainerActiveRecord]] you need to implement following abstract methods:
|
||||
If you're implementing an ActiveRecord based on [[humhub\modules\content\components\ContentContainerActiveRecord]] you need to implement the following abstract methods:
|
||||
|
||||
- getContentName() - Returns the displayed name of the Content (e.g. Post or Poll)
|
||||
- getContentDescription() - Returns a preview of the Content - which is used in Notifications for example.
|
||||
- `getContentName()` - Returns the displayed name of the Content (e.g. Post or Poll)
|
||||
- `getContentDescription()` - Returns a preview of the Content - which is used in Notifications for example.
|
||||
|
||||
Example:
|
||||
|
||||
@ -150,22 +150,17 @@ Example:
|
||||
|
||||
```
|
||||
|
||||
|
||||
#### Wall/Stream Output
|
||||
|
||||
(TBD)
|
||||
|
||||
#### Querying Content
|
||||
|
||||
If you're calling find() on a [[\humhub\modules\content\components\ContentActiveRecord]] instance you'll get an special [[\humhub\modules\content\components\ActiveQueryContent]] which provides additional method to select content.
|
||||
If you're calling find() on a [[\humhub\modules\content\components\ContentActiveRecord]] instance you'll get an special [[\humhub\modules\content\components\ActiveQueryContent]] which provides additional methods to select content.
|
||||
|
||||
- contentContainer($container) - Find content only inside a given container
|
||||
- readable($user) - Return only user readable content
|
||||
- ...
|
||||
|
||||
#### Permissions
|
||||
|
||||
TBD (Read Permissions not enhanceable)
|
||||
|
||||
|
||||
### Controller
|
||||
|
||||
|
87
protected/humhub/docs/guide/dev-db.md
Normal file
87
protected/humhub/docs/guide/dev-db.md
Normal file
@ -0,0 +1,87 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
## Integrity Checker
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
@ -1,63 +0,0 @@
|
||||
# Enviroment
|
||||
|
||||
## Enable Yii Debug Module
|
||||
|
||||
Add following block to your local web configuration (/protected/config/web.php)
|
||||
|
||||
```php
|
||||
<?php
|
||||
return [
|
||||
// ...
|
||||
'bootstrap' => ['debug'],
|
||||
'modules' => [
|
||||
// ...
|
||||
|
||||
'debug' => [
|
||||
'class' => 'yii\debug\Module',
|
||||
'allowedIPs' => ['127.0.0.1', '::1'],
|
||||
],
|
||||
|
||||
// ...
|
||||
]
|
||||
];
|
||||
?>
|
||||
```
|
||||
|
||||
## Enable Gii
|
||||
|
||||
### Web
|
||||
|
||||
Add following block to your local web configuration (/protected/config/web.php)
|
||||
|
||||
```php
|
||||
return [
|
||||
// ...
|
||||
'modules' => [
|
||||
// ...
|
||||
|
||||
'gii' => [
|
||||
'class' => 'yii\gii\Module',
|
||||
'allowedIPs' => ['127.0.0.1', '::1'],
|
||||
],
|
||||
|
||||
// ...
|
||||
]
|
||||
];
|
||||
?>
|
||||
```
|
||||
|
||||
|
||||
### Console
|
||||
|
||||
Add following block to your local console configuration (/protected/config/console.php)
|
||||
|
||||
```php
|
||||
return [
|
||||
// ...
|
||||
'bootstrap' => ['gii'],
|
||||
'modules' => [
|
||||
'gii' => 'yii\gii\Module',
|
||||
],
|
||||
// ...
|
||||
];
|
||||
```
|
@ -6,9 +6,112 @@ Overview
|
||||
- HumHub is based on Yii 2.0 PHP Framework (http://www.yiiframework.com/)
|
||||
- [The Definitive Guide to Yii 2.0](http://www.yiiframework.com/doc-2.0/guide-index.html)
|
||||
|
||||
## Application Overview
|
||||
|
||||
Humhub is based on _PHP5_ and _Yii2_ and leverages the highly modular and flexible nature of _Yii_.
|
||||
Before learning about the internals of HumHub, you should be familiar with the basic concepts of
|
||||
[Yii](http://www.yiiframework.com/doc-2.0/guide-README.html "Yii Guide").
|
||||
|
||||
![Application Layers](images/appLayer.svg)
|
||||
|
||||
The HumHub core contains several core modules as well as extended Yii components:
|
||||
|
||||
**Core Components:**
|
||||
|
||||
- [[humhub\components\ActiveRecord]]
|
||||
- [[humhub\components\Application]]
|
||||
- [[humhub\components\Controller]]
|
||||
- [[humhub\components\Migration]]
|
||||
- [[humhub\components\Module]]
|
||||
- [[humhub\components\ModuleManager]]
|
||||
- [[humhub\components\Request]]
|
||||
- [[humhub\components\Theme]]
|
||||
- [[humhub\components\View]]
|
||||
- [[humhub\components\Widget]]
|
||||
|
||||
**Core Modules:**
|
||||
|
||||
- **activity:** User/Space activities
|
||||
- **admin:** Responsible for admin/configuration related issues
|
||||
- **comment:** Content addon for commenting
|
||||
- **content:** Base module for all content types (Post,Wiki,...)
|
||||
- **dashboard:** Dashboard related functionality
|
||||
- **directory:** Directory related functionality
|
||||
- **file:** Basic file module for accessing the filesystem
|
||||
- **installer:** HumHub installer module
|
||||
- **like:** Content addon for likes
|
||||
- **notification:** User Notifications
|
||||
- **post:** Simple user-post related functionality
|
||||
- **search:** Luceene Search Module
|
||||
- **space:** Space related functionality
|
||||
- **tour:** HumHub user-guide
|
||||
- **user:** Basic user module
|
||||
|
||||
## Development Environment Notes
|
||||
|
||||
- Use Composer Installation include dev requirements
|
||||
- Switch to development mode in ``index.php`` (see inline documentation)
|
||||
- Disable Caching (Administration -> Settings -> Caching -> None)
|
||||
- Use Composer Installation as described in the [Installation Guide](admin-installation.md#via-gitcomposer)
|
||||
- Switch to development mode in ``index.php`` (described [here](admin-installation.md#disable-errors-debugging))
|
||||
- Disable Caching under **Administration -> Settings -> Caching -> None**
|
||||
|
||||
## Enable Yii Debug Module
|
||||
|
||||
Add following block to your local web configuration (/protected/config/web.php)
|
||||
|
||||
```php
|
||||
<?php
|
||||
return [
|
||||
// ...
|
||||
'bootstrap' => ['debug'],
|
||||
'modules' => [
|
||||
// ...
|
||||
|
||||
'debug' => [
|
||||
'class' => 'yii\debug\Module',
|
||||
'allowedIPs' => ['127.0.0.1', '::1'],
|
||||
],
|
||||
|
||||
// ...
|
||||
]
|
||||
];
|
||||
?>
|
||||
```
|
||||
|
||||
## Enable Gii
|
||||
|
||||
### Web
|
||||
|
||||
Add following block to your local web configuration (/protected/config/web.php)
|
||||
|
||||
```php
|
||||
return [
|
||||
// ...
|
||||
'modules' => [
|
||||
// ...
|
||||
|
||||
'gii' => [
|
||||
'class' => 'yii\gii\Module',
|
||||
'allowedIPs' => ['127.0.0.1', '::1'],
|
||||
],
|
||||
|
||||
// ...
|
||||
]
|
||||
];
|
||||
?>
|
||||
```
|
||||
|
||||
|
||||
### Console
|
||||
|
||||
Add following block to your local console configuration (/protected/config/console.php)
|
||||
|
||||
```php
|
||||
return [
|
||||
// ...
|
||||
'bootstrap' => ['gii'],
|
||||
'modules' => [
|
||||
'gii' => 'yii\gii\Module',
|
||||
],
|
||||
// ...
|
||||
];
|
||||
```
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Here you will learn how you can adapt existing modules to working fine with actually versions.
|
||||
|
||||
## to 1.1
|
||||
## Migrate from 1.0 to 1.1
|
||||
|
||||
- Dropped unused space attribute "website"
|
||||
|
||||
@ -14,27 +14,36 @@ Here you will learn how you can adapt existing modules to working fine with actu
|
||||
- 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](dev-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
|
||||
|
||||
|
||||
## to 0.20
|
||||
## 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](dev-migrate-0.20.md)
|
||||
|
||||
## to 0.12
|
||||
## Migrate from 0.11 to 0.12
|
||||
|
||||
- Rewritten Search
|
||||
|
||||
## to 0.11
|
||||
## 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
|
||||
|
||||
## to 0.10
|
||||
|
||||
No breaking changes
|
||||
- New Wiki Parser / Editor Widget
|
@ -1,77 +0,0 @@
|
||||
Activities
|
||||
==========
|
||||
|
||||
Contrary to Notifications - Activities are bound to a ContentContainer, so they are not especially linked against a user or a given set of them.
|
||||
|
||||
Besides the link to the ContentContainer - an Activity can be also assigned to a Content or ContentAddon. So it will automatically inherits some Content Attributes such as Visiblity.
|
||||
|
||||
Note: Internally Activities will be handled as Content.
|
||||
|
||||
## Steps to create an Activity
|
||||
|
||||
### Create Class & View
|
||||
|
||||
Create a folder ** activities ** in your module and a new class ** SomethingHappend **
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace johndoe\example\activities;
|
||||
|
||||
use humhub\core\activity\components\BaseActivity;
|
||||
|
||||
/**
|
||||
* Notifies a user about something happend
|
||||
*/
|
||||
class SomethingHappend extends BaseActivity
|
||||
{
|
||||
// View Name for activity
|
||||
public $viewName = "somethingHappend";
|
||||
|
||||
// Module Id (required)
|
||||
public $moduleId = "example";
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
```
|
||||
|
||||
By default activity views should be located inside a subfolder named ** views ** where your activity class is located. (e.g. /modules/examples/activities/views/)
|
||||
|
||||
Example view file ** somethingHappend.php **:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use yii\helpers\Html;
|
||||
|
||||
echo Yii::t('ExampleModule.views_notifications_newLike', "%someUser% did something cool.", array(
|
||||
'%someUser%' => '<strong>' . Html::encode($originator->displayName) . '</strong>'
|
||||
));
|
||||
?>
|
||||
|
||||
|
||||
```
|
||||
|
||||
If you require a diffrent view in mails. You can create a subfolder inside the subfolder called ** mail ** in your views directory.
|
||||
|
||||
|
||||
### Create it
|
||||
|
||||
```php
|
||||
$activity = new \johndoe\example\activities\NewLike();
|
||||
|
||||
// Link to a ContentContainer, Content or ContentAddon
|
||||
$activity->source = $this;
|
||||
|
||||
// User which trigged this Activity - in case of Content/ContentAddon the Creator will be automatically set.
|
||||
$activity->originator = $user;
|
||||
|
||||
$activity->create();
|
||||
```
|
||||
|
||||
|
||||
### Delete
|
||||
|
||||
TBD
|
@ -1,35 +0,0 @@
|
||||
Console
|
||||
=======
|
||||
|
||||
To add a custom controller to the console application, you need to catch the [[humhub\components\console\Application::EVENT_ON_INIT]].
|
||||
|
||||
|
||||
### Example: Event
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use humhub\components\console\Application;
|
||||
|
||||
return [
|
||||
'id' => 'translation',
|
||||
'class' => 'humhub\modules\translation\Module',
|
||||
'namespace' => 'humhub\modules\translation',
|
||||
'events' => array(
|
||||
//...
|
||||
array('class' => Application::className(), 'event' => Application::EVENT_ON_INIT, 'callback' => array('humhub\modules\translation\Module', 'onConsoleApplicationInit')),
|
||||
//...
|
||||
),
|
||||
];
|
||||
?>
|
||||
```
|
||||
|
||||
### Example: Callback
|
||||
|
||||
```php
|
||||
public static function onConsoleApplicationInit($event) {
|
||||
$application = $event->sender;
|
||||
$application->controllerMap['translation'] = commands\TranslationController::className();
|
||||
}
|
||||
|
||||
```
|
@ -1,66 +0,0 @@
|
||||
Database
|
||||
========
|
||||
|
||||
### 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
|
||||
|
||||
TBD
|
||||
|
||||
[[humhub\components\ActiveRecord]]
|
||||
|
||||
|
||||
### 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.
|
||||
|
||||
|
||||
** Examples: **
|
||||
|
||||
|
||||
- Create a module migration
|
||||
> php yii migrate/create example --migrationPath='@app/modules/polls/migrations'
|
||||
|
||||
- Execute module migrations
|
||||
> 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;
|
||||
}
|
||||
|
||||
}
|
||||
```
|
@ -1,66 +0,0 @@
|
||||
Modules - General
|
||||
=================
|
||||
|
||||
Basically modules in HumHub are identical to Yii2 modules [http://www.yiiframework.com/doc-2.0/guide-structure-modules.html](http://www.yiiframework.com/doc-2.0/guide-structure-modules.html).
|
||||
|
||||
You can use either the Yii's module base class [[yii\base\Module]] or the enhanced HumHub module base class [[humhub\components\Module]].
|
||||
|
||||
The enhanced HumHub module class provides additional features like:
|
||||
- Dynamic module management (enable / disable / install / uninstall) via administration interface
|
||||
- Usable as Space or User Profile module
|
||||
|
||||
|
||||
config.php
|
||||
-------------
|
||||
|
||||
If the module is placed inside the */protected/modules* folder, you can create a *config.php* in the module directory which provides automatic loading without manually modifing the application config.
|
||||
|
||||
The config.php should return an array including following fields:
|
||||
|
||||
- **id** - Unqiue ID of the module (required)
|
||||
- **class** - Namespaced classname of the module (required)
|
||||
- **events** - Array of Events (optional)
|
||||
- **namespace** - Namespace of your module
|
||||
- **urlManagerRules** - Array of URL Manager Rules [http://www.yiiframework.com/doc-2.0/yii-web-urlmanager.html#addRules()-detail](http://www.yiiframework.com/doc-2.0/yii-web-urlmanager.html#addRules()-detail)
|
||||
- **modules** - Submodules (optional)
|
||||
|
||||
Example of a config.php file:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use johndoe\example\Module;
|
||||
use humhub\widgets\TopMenu;
|
||||
|
||||
return [
|
||||
'id' => 'example',
|
||||
'class' => 'johndoe\example\Module',
|
||||
'namespace' => 'johndoe\example',
|
||||
'events' => [
|
||||
array('class' => TopMenu::className(), 'event' => TopMenu::EVENT_INIT, 'callback' => array('johndoe\example\Module', 'onTopMenuInit')),
|
||||
]
|
||||
];
|
||||
?>
|
||||
```
|
||||
|
||||
**Note: ** Do not execute any code in the config.php - the result will be cached!
|
||||
|
||||
|
||||
module.json
|
||||
-----------
|
||||
|
||||
This file holds basic information about the module like name, description or current version. Locate this file in the root directory of the module.
|
||||
|
||||
Example of a ´´module.json file:
|
||||
```
|
||||
{
|
||||
"id": "example",
|
||||
"name": "My Example Module",
|
||||
"description": "My testing module.",
|
||||
"keywords": ["my", "cool", "module"],
|
||||
"version": "1.0",
|
||||
"humhub": {
|
||||
"minVersion": "0.20"
|
||||
}
|
||||
}
|
||||
```
|
@ -1,44 +0,0 @@
|
||||
Menus
|
||||
=====
|
||||
|
||||
All navigations widget classes inherits the base class [[humhub\widgets\BaseMenu]] which allows modules
|
||||
to inject own items into navigation menu.
|
||||
|
||||
## Example
|
||||
|
||||
__config.php__ - Catching Event
|
||||
|
||||
```php
|
||||
//...
|
||||
use humhub\widgets\TopMenu;
|
||||
//...
|
||||
'events' => array(
|
||||
array('class' => TopMenu::className(), 'event' => TopMenu::EVENT_INIT, 'callback' => array('humhub\modules\calendar\Events', 'onTopMenuInit')),
|
||||
),
|
||||
//...
|
||||
```
|
||||
|
||||
|
||||
__Events.php__ - Handling the Event
|
||||
|
||||
```php
|
||||
//...
|
||||
public static function onTopMenuInit($event)
|
||||
{
|
||||
if (Yii::$app->user->isGuest) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user = Yii::$app->user->getIdentity();
|
||||
if ($user->isModuleEnabled('calendar')) {
|
||||
$event->sender->addItem(array(
|
||||
'label' => Yii::t('CalendarModule.base', 'Calendar'),
|
||||
'url' => Url::to(['/calendar/global/index']),
|
||||
'icon' => '<i class="fa fa-calendar"></i>',
|
||||
'isActive' => (Yii::$app->controller->module && Yii::$app->controller->module->id == 'calendar' && Yii::$app->controller->id == 'global'),
|
||||
'sortOrder' => 300,
|
||||
));
|
||||
}
|
||||
}
|
||||
//...
|
||||
```
|
@ -1,37 +0,0 @@
|
||||
Settings
|
||||
========
|
||||
|
||||
|
||||
Global Settings
|
||||
---------------
|
||||
|
||||
Example:
|
||||
|
||||
```php
|
||||
HSetting::Set('someName', 'someValue' ,'exampleModuleId');
|
||||
$mySetting = HSetting::Get('someName', 'exampleModuleId');
|
||||
```
|
||||
|
||||
|
||||
|
||||
User Settings
|
||||
-------------
|
||||
|
||||
Example:
|
||||
|
||||
```php
|
||||
$user->setSetting("someName", "someValue", "exampleModuleId");
|
||||
$mySetting = $user->getSetting("someName", "exampleModuleId");
|
||||
```
|
||||
|
||||
|
||||
|
||||
Space Settings
|
||||
--------------
|
||||
|
||||
Example:
|
||||
|
||||
```php
|
||||
$space->setSetting("someName", "someValue", "exampleModuleId");
|
||||
$mySetting = $space->getSetting("someName", "exampleModuleId");
|
||||
```
|
@ -1,44 +0,0 @@
|
||||
Space/User Modules
|
||||
==================
|
||||
|
||||
TBD
|
||||
|
||||
|
||||
|
||||
## Enabled/Disable per Space/User
|
||||
|
||||
|
||||
Tasks:
|
||||
- Inherit your modules base class from [[\humhub\modules\content\components\ContentContainerModule]]
|
||||
- Define valid container types (e.g. Space or/and User)
|
||||
|
||||
Example
|
||||
|
||||
```php
|
||||
|
||||
// ...
|
||||
use humhub\modules\space\models\Space;
|
||||
use humhub\modules\user\models\User;
|
||||
// ...
|
||||
|
||||
class Module extends \humhub\modules\content\components\ContentContainerModule
|
||||
{
|
||||
|
||||
// ...
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function getContentContainerTypes()
|
||||
{
|
||||
return [
|
||||
Space::className(),
|
||||
User::className(),
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
// ...
|
||||
|
||||
}
|
||||
|
||||
```
|
@ -1,27 +0,0 @@
|
||||
Special Topics
|
||||
==============
|
||||
|
||||
## Integrity Checker
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -1,45 +0,0 @@
|
||||
Widget Stack
|
||||
============
|
||||
|
||||
- Base class: [[humhub\widgets\BaseStack]]
|
||||
- Use Cases: Sidebars, ...
|
||||
|
||||
TBD
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
Example of stack used as sidebar.
|
||||
|
||||
```php
|
||||
<?php
|
||||
echo \humhub\core\space\widgets\Sidebar::widget(['widgets' => [
|
||||
[\humhub\core\activity\widgets\Stream::className(), ['streamAction' => '/space/space/stream', 'contentContainer' => $space], ['sortOrder' => 10]],
|
||||
[\humhub\core\space\widgets\Members::className(), ['space' => $space], ['sortOrder' => 20]]
|
||||
]]);
|
||||
?>
|
||||
```
|
||||
|
||||
## Events
|
||||
|
||||
### Example
|
||||
|
||||
__config.php__
|
||||
|
||||
```php
|
||||
//...
|
||||
'events' => array(
|
||||
// Wait for TopMenu Initalization Event
|
||||
array('class' => 'DashboardSidebarWidget', 'event' => 'onInit', 'callback' => array('ExampleModule', 'onDashboardSidebarInit')),
|
||||
),
|
||||
//...
|
||||
```
|
||||
|
||||
|
||||
__Events.php__
|
||||
|
||||
```php
|
||||
public static function onDashboardSidebarInit($event) {
|
||||
$event->sender->addWidget('application.modules.example.widgets.MyCoolWidget', array(), array('sortOrder' => 1));
|
||||
}
|
||||
```
|
@ -1,161 +0,0 @@
|
||||
# Streams / Walls
|
||||
|
||||
TBD
|
||||
|
||||
- Define Streaming/Wall
|
||||
|
||||
You can also implement Creanown Stream/Wall output for your module content only.
|
||||
|
||||
Example Implementations:
|
||||
|
||||
- Tasks
|
||||
- Polls
|
||||
|
||||
Of course your modules Content implementation needs to provides a WallEntry widget. See Content Section for more details.
|
||||
|
||||
|
||||
## Create own Module Content Stream
|
||||
|
||||
### Implement StreamAction
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
public function setupFilters()
|
||||
{
|
||||
// Limit output to specific content type
|
||||
$this->activeQuery->andWhere(['content.object_model' => Poll::className()]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Specify Action in Controller
|
||||
|
||||
Example:
|
||||
|
||||
```php
|
||||
class PollController extends ContentContainerController
|
||||
{
|
||||
|
||||
public function actions()
|
||||
{
|
||||
return array(
|
||||
'stream' => array(
|
||||
'class' => \humhub\modules\polls\components\StreamAction::className(),
|
||||
'mode' => \humhub\modules\polls\components\StreamAction::MODE_NORMAL,
|
||||
'contentContainer' => $this->contentContainer
|
||||
),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Display Stream
|
||||
|
||||
You can use the Stream Widget to display the Stream in your View.
|
||||
|
||||
```php
|
||||
|
||||
echo \humhub\modules\content\widgets\Stream::widget(array(
|
||||
'contentContainer' => $contentContainer,
|
||||
'streamAction' => '//polls/poll/stream',
|
||||
'messageStreamEmpty' => ($contentContainer->canWrite()) ?
|
||||
Yii::t('PollsModule.widgets_views_stream', '<b>There are no polls yet!</b><br>Be the first and create one...') :
|
||||
Yii::t('PollsModule.widgets_views_stream', '<b>There are no polls yet!</b>'),
|
||||
'messageStreamEmptyCss' => ($contentContainer->canWrite()) ?
|
||||
'placeholder-empty-stream' :
|
||||
'',
|
||||
));
|
||||
|
||||
```
|
||||
|
||||
## Create Content Form
|
||||
|
||||
### Create Form Widget
|
||||
|
||||
Create a Form Widget derived from [[humhub\modules\content\widgets\WallCreateContentForm]]
|
||||
|
||||
```php
|
||||
|
||||
namespace humhub\modules\polls\widgets;
|
||||
|
||||
class WallCreateForm extends \humhub\modules\content\widgets\WallCreateContentForm
|
||||
{
|
||||
|
||||
public $submitUrl = '/polls/poll/create';
|
||||
|
||||
public function renderForm()
|
||||
{
|
||||
// Render your custom form here
|
||||
return $this->render('form', array());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Create a view file for widget which contains module specific fields. All standard fields (e.g. visibility) are added automatically.
|
||||
|
||||
```php
|
||||
<?php echo Html::textArea("question", "", array('id' => 'contentForm_question', 'class' => 'form-control autosize contentForm', 'rows' => '1', "tabindex" => "1", "placeholder" => Yii::t('PollsModule.widgets_views_pollForm', "Ask something..."))); ?>
|
||||
|
||||
<div class="contentForm_options">
|
||||
<?php echo Html::textArea("answersText", "", array('id' => "contentForm_answersText", 'rows' => '5', 'style' => 'height: auto !important;', "class" => "form-control contentForm", "tabindex" => "2", "placeholder" => Yii::t('PollsModule.widgets_views_pollForm', "Possible answers (one per line)"))); ?>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<?php echo Html::checkbox("allowMultiple", "", array('id' => "contentForm_allowMultiple", 'class' => 'checkbox contentForm', "tabindex" => "4")); ?> <?php echo Yii::t('PollsModule.widgets_views_pollForm', 'Allow multiple answers per user?'); ?>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
### Create Create Action
|
||||
|
||||
Create an action in your modules controller to receive form inputs.
|
||||
|
||||
All default tasks (e.g. access validation, ContentContainer assignment) are handled by [[humhub\modules\content\widgets\WallCreateContentForm::create]]
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
```php
|
||||
|
||||
public function actionCreate()
|
||||
{
|
||||
$poll = new Poll();
|
||||
$poll->question = Yii::$app->request->post('question');
|
||||
$poll->answersText = Yii::$app->request->post('answersText');
|
||||
$poll->allow_multiple = Yii::$app->request->post('allowMultiple', 0);
|
||||
|
||||
return \humhub\modules\polls\widgets\WallCreateForm::create($poll);
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
### Display Form
|
||||
|
||||
Place the Form widget above the Stream widget in your view.
|
||||
|
||||
e.g.
|
||||
|
||||
```php
|
||||
|
||||
<?php echo \humhub\modules\polls\widgets\WallCreateForm::widget(array('contentContainer' => $contentContainer)); ?>
|
||||
|
||||
```
|
||||
|
64
protected/humhub/docs/guide/dev-module.md
Normal file
64
protected/humhub/docs/guide/dev-module.md
Normal file
@ -0,0 +1,64 @@
|
||||
Modules - Getting Started
|
||||
=================
|
||||
|
||||
Basically modules in HumHub are identical to Yii2 modules [http://www.yiiframework.com/doc-2.0/guide-structure-modules.html](http://www.yiiframework.com/doc-2.0/guide-structure-modules.html).
|
||||
|
||||
You can use either the Yii's module base class [[yii\base\Module]] or the enhanced HumHub module base class [[humhub\components\Module]].
|
||||
|
||||
The enhanced HumHub module class provides additional features like:
|
||||
- Dynamic module management (enable / disable / install / uninstall) via administration interface
|
||||
- Usable as Space or User Profile module
|
||||
|
||||
|
||||
## config.php
|
||||
|
||||
|
||||
If the module is placed inside the */protected/modules* folder, you can create a *config.php* in the module directory which provides automatic loading without manually modifing the application config.
|
||||
|
||||
The config.php should return an array including following fields:
|
||||
|
||||
- **id** - Unqiue ID of the module (required)
|
||||
- **class** - Namespaced classname of the module (required)
|
||||
- **events** - Array of Events (optional)
|
||||
- **namespace** - Namespace of your module
|
||||
- **urlManagerRules** - Array of URL Manager Rules [http://www.yiiframework.com/doc-2.0/yii-web-urlmanager.html#addRules()-detail](http://www.yiiframework.com/doc-2.0/yii-web-urlmanager.html#addRules()-detail)
|
||||
- **modules** - Submodules (optional)
|
||||
|
||||
Example of a config.php file:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use johndoe\example\Module;
|
||||
use humhub\widgets\TopMenu;
|
||||
|
||||
return [
|
||||
'id' => 'example',
|
||||
'class' => 'johndoe\example\Module',
|
||||
'namespace' => 'johndoe\example',
|
||||
'events' => [
|
||||
array('class' => TopMenu::className(), 'event' => TopMenu::EVENT_INIT, 'callback' => array('johndoe\example\Module', 'onTopMenuInit')),
|
||||
]
|
||||
];
|
||||
?>
|
||||
```
|
||||
|
||||
> Note: Do not execute any code in the __config.php__ - the result will be cached!
|
||||
|
||||
|
||||
## module.json
|
||||
|
||||
This file holds basic information about the module like name, description or current version. Locate this file in the root directory of the module.
|
||||
|
||||
```
|
||||
{
|
||||
"id": "example",
|
||||
"name": "My Example Module",
|
||||
"description": "My testing module.",
|
||||
"keywords": ["my", "cool", "module"],
|
||||
"version": "1.0",
|
||||
"humhub": {
|
||||
"minVersion": "0.20"
|
||||
}
|
||||
}
|
||||
```
|
@ -1,15 +1,32 @@
|
||||
Notifications
|
||||
=============
|
||||
|
||||
Notifications are derived from [[humhub\modules\notification\components\BaseNotification]] and are used to inform one or a given set of users about a specific event.
|
||||
Notifications are used to inform one or a given set of users about a specific event as the liking of a post or mentioning of a user, over multiple channels (e.g. web and mail).
|
||||
|
||||
Custom notification types are derived from [[humhub\modules\notification\components\BaseNotification]] and can be assigned with an optional `$originator` user instance, which links
|
||||
the notification with the user who triggered the event. Furthermore the [[humhub\modules\notification\components\BaseNotification|BaseNotification]] can be assigned with a `$source` of type [[yii\db\ActiveRecord]],
|
||||
which links the notification to a source instance like a Content or ContentAddon (e.g. a Post or Like).
|
||||
|
||||
The BaseNotification is responsible for:
|
||||
|
||||
- **instantiating** and **persisting** [[humhub\modules\notification\models\Notification]] model instances.
|
||||
- **rendering** the notification output for the differen output channels.
|
||||
|
||||
![Notification Class Diagram](images/notificationClassDiag.jpg)
|
||||
|
||||
### Create Notifications
|
||||
Examples for core notifications are:
|
||||
|
||||
Notifications should reside in the `notifications` directory of a module. (e.g. `/modules/examples/notifications/`)
|
||||
- [[humhub\modules\like\notifications\NewLike]]: is sent if an user likes a post or comment.
|
||||
- [[humhub\modules\user\notifications\Followed]]: is sent if an user follows another user.
|
||||
- [[humhub\modules\user\notifications\Mentioned]]: is sent if an user is mentioned within an post or comment.
|
||||
- [[humhub\modules\content\notifications\ContentCreated]]: is sent when content (e.g. a post) was created.
|
||||
|
||||
Example notification:
|
||||
## Custom Notifications
|
||||
|
||||
#### Notification Class
|
||||
|
||||
Custom Notifications are derived from [[humhub\modules\notification\components\BaseNotification|BaseNotification]] and should reside in the a subfolder `notifications` of your module directory.
|
||||
The notification class at least has to overwrite the `$moduleId` variable with the id of your module and the `$viewName` with the name of the view which is used to render the notification.
|
||||
|
||||
```php
|
||||
<?php
|
||||
@ -23,37 +40,45 @@ use humhub\modules\notification\components\BaseNotification;
|
||||
*/
|
||||
class SomethingHappend extends BaseNotification
|
||||
{
|
||||
// Module Id (required)
|
||||
public $moduleId = "example";
|
||||
// Module Id (required)
|
||||
public $moduleId = "example";
|
||||
|
||||
// Viewname (required)
|
||||
public $viewName = "somethingHappend";
|
||||
}
|
||||
?>
|
||||
```
|
||||
|
||||
By default, the view of a notification should be located inside a subfolder `notifications/views`. (e.g. `/modules/examples/notifications/views/`)
|
||||
#### Notification View
|
||||
|
||||
Example view file _somethingHappend.php_:
|
||||
By default, the view of a notification should be located inside the subfolder `notifications/views`.
|
||||
The view of our example is therefore located in `/modules/examples/notifications/views/somethingHappened.php`.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
use yii\helpers\Html;
|
||||
|
||||
echo Yii::t('LikeModule.views_notifications_newLike', "%someUser% did something cool.", array(
|
||||
echo Yii::t('SomethingHappend.views_notifications_somethingHappened', "%someUser% did something cool.", [
|
||||
'%someUser%' => '<strong>' . Html::encode($originator->displayName) . '</strong>'
|
||||
));
|
||||
]);
|
||||
?>
|
||||
```
|
||||
|
||||
> Info: If you require a different notification view for mails. You have to add a view file to a subfolder `notifications/views/mail`.
|
||||
> Info: If you require a different notification view for mails, you have to add an extra view file to a subfolder `notifications/views/mail`.
|
||||
|
||||
### Send Notifications
|
||||
## Send Notifications
|
||||
|
||||
After an event was triggered you'll have to instantiate your custom [[humhub\modules\notification\components\BaseNotification|BaseNotification]] and call its
|
||||
`send` or `sendBulk` which will instantiate and persist a [[humhub\modules\notification\models\Notification]] instance for every user you want to notify.
|
||||
|
||||
A notification can optionally be assigned with a `$source` model instance (e.g. a post or comment related to the notification) which has to be derived from [[yii\db\ActiveRecord]].
|
||||
If the notification was created in the context of a space (e.g. `$source` is a Content, ContentAddon or ContentContainer) the `$space` variable is set with the related space instance automatically.
|
||||
|
||||
```php
|
||||
$notification = new \johndoe\example\notifications\SomethingHappend();
|
||||
|
||||
// Link to the object which fired the notification (optional)
|
||||
// Link to the object which fired the notification e.g. a SomethingHappened content-addon (optional)
|
||||
$notification->source = $this;
|
||||
|
||||
// The user which triggered the notification (optional)
|
||||
@ -65,9 +90,14 @@ $notification->sendBulk(User::find()->where([...]));
|
||||
// or: a single user
|
||||
$notification->send($user);
|
||||
```
|
||||
> Info: The `send` and `sendBulk` will create and persist an own [[humhub\modules\notification\models\Notification]] for each user.
|
||||
|
||||
> Info: The `send` and `sendBulk` will create and persist a [[humhub\modules\notification\models\Notification]] instance for each user.
|
||||
|
||||
### Delete Notifications
|
||||
> Tip: Notifications are often created and sent within the `afterSave` hook of the related `source` instance. This should be prefered over the instantiation within a controller.
|
||||
|
||||
> Note: Notifications are only sent by mail depending on the users account settings.
|
||||
|
||||
## Delete Notifications
|
||||
|
||||
By default notifications will automatically be deleted after a given period of time or if the originator(user) object is removed.
|
||||
|
||||
@ -77,4 +107,4 @@ Example for manual notification deletion:
|
||||
$notification = new johndoe\example\notifications\SomethingHappend();
|
||||
$notification->source = $this;
|
||||
$notification->delete(User::findOne(['id' => $userId]));
|
||||
```
|
||||
```
|
@ -1,40 +0,0 @@
|
||||
Application Overview
|
||||
=======
|
||||
|
||||
Humhub is based on **PHP5** and **Yii2** and leverages the highly modular and flexible nature of *Yii*.
|
||||
Before learning about the internals of HumHub, you should be familiar with the basic concepts of the
|
||||
[Yii Framework](http://www.yiiframework.com/doc-2.0/guide-README.html "Yii Framework").
|
||||
The HumHub core contains of several core modules as well as extended Yii components:
|
||||
|
||||
**Core Components:**
|
||||
|
||||
- [[humhub\components\ActiveRecord]]:
|
||||
- [[humhub\components\Application]]
|
||||
- [[humhub\components\Controller]]
|
||||
- [[humhub\components\Migration]]
|
||||
- [[humhub\components\Module]]
|
||||
- [[humhub\components\ModuleManager]]
|
||||
- [[humhub\components\Request]]
|
||||
- [[humhub\components\Theme]]
|
||||
- [[humhub\components\View]]
|
||||
- [[humhub\components\Widget]]
|
||||
|
||||
**Core Modules:**
|
||||
|
||||
- **activity:** User/Space activities
|
||||
- **admin:** Responsible for admin/configuration related issues
|
||||
- **comment:** Content addon for commenting
|
||||
- **content:** Base module for all content types (Post,Wiki,...)
|
||||
- **dashboard:** Dashboard related functionality
|
||||
- **directory:** Directory related functionality
|
||||
- **file:** Basic file module for accessing the filesystem
|
||||
- **installer:** HumHub installer module
|
||||
- **like:** Content addon for likes
|
||||
- **notification:** User Notifications
|
||||
- **post:** Simple user-post related functionality
|
||||
- **search:** Luceene Search Module
|
||||
- **space:** Space related functionality
|
||||
- **tour:** HumHub user-guide
|
||||
- **user:** Basic user module
|
||||
|
||||
![Application Layers](images/appLayer.svg)
|
3
protected/humhub/docs/guide/dev-permissions.md
Normal file
3
protected/humhub/docs/guide/dev-permissions.md
Normal file
@ -0,0 +1,3 @@
|
||||
Permissions
|
||||
========
|
||||
(TBD)
|
75
protected/humhub/docs/guide/dev-settings.md
Normal file
75
protected/humhub/docs/guide/dev-settings.md
Normal 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');
|
||||
```
|
161
protected/humhub/docs/guide/dev-stream.md
Normal file
161
protected/humhub/docs/guide/dev-stream.md
Normal file
@ -0,0 +1,161 @@
|
||||
# Streams / Walls
|
||||
|
||||
TBD
|
||||
|
||||
- Define Streaming/Wall
|
||||
|
||||
You can also implement Creanown Stream/Wall output for your module content only.
|
||||
|
||||
Example Implementations:
|
||||
|
||||
- Tasks
|
||||
- Polls
|
||||
|
||||
Of course your modules Content implementation needs to provides a WallEntry widget. See Content Section for more details.
|
||||
|
||||
|
||||
## Create own Module Content Stream
|
||||
|
||||
### Implement StreamAction
|
||||
|
||||
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
|
||||
{
|
||||
|
||||
public function setupFilters()
|
||||
{
|
||||
// Limit output to specific content type
|
||||
$this->activeQuery->andWhere(['content.object_model' => Poll::className()]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Specify Action in Controller
|
||||
|
||||
Example:
|
||||
|
||||
```php
|
||||
class PollController extends ContentContainerController
|
||||
{
|
||||
|
||||
public function actions()
|
||||
{
|
||||
return array(
|
||||
'stream' => array(
|
||||
'class' => \humhub\modules\polls\components\StreamAction::className(),
|
||||
'mode' => \humhub\modules\polls\components\StreamAction::MODE_NORMAL,
|
||||
'contentContainer' => $this->contentContainer
|
||||
),
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### Display Stream
|
||||
|
||||
You can use the Stream Widget to display the Stream in your View.
|
||||
|
||||
```php
|
||||
|
||||
echo \humhub\modules\content\widgets\Stream::widget(array(
|
||||
'contentContainer' => $contentContainer,
|
||||
'streamAction' => '//polls/poll/stream',
|
||||
'messageStreamEmpty' => ($contentContainer->canWrite()) ?
|
||||
Yii::t('PollsModule.widgets_views_stream', '<b>There are no polls yet!</b><br>Be the first and create one...') :
|
||||
Yii::t('PollsModule.widgets_views_stream', '<b>There are no polls yet!</b>'),
|
||||
'messageStreamEmptyCss' => ($contentContainer->canWrite()) ?
|
||||
'placeholder-empty-stream' :
|
||||
'',
|
||||
));
|
||||
|
||||
```
|
||||
|
||||
## Create Content Form
|
||||
|
||||
### Create Form Widget
|
||||
|
||||
Create a Form Widget derived from [[humhub\modules\content\widgets\WallCreateContentForm]]
|
||||
|
||||
```php
|
||||
|
||||
namespace humhub\modules\polls\widgets;
|
||||
|
||||
class WallCreateForm extends \humhub\modules\content\widgets\WallCreateContentForm
|
||||
{
|
||||
|
||||
public $submitUrl = '/polls/poll/create';
|
||||
|
||||
public function renderForm()
|
||||
{
|
||||
// Render your custom form here
|
||||
return $this->render('form', array());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Create a view file for widget which contains module specific fields. All standard fields (e.g. visibility) are added automatically.
|
||||
|
||||
```php
|
||||
<?php echo Html::textArea("question", "", array('id' => 'contentForm_question', 'class' => 'form-control autosize contentForm', 'rows' => '1', "tabindex" => "1", "placeholder" => Yii::t('PollsModule.widgets_views_pollForm', "Ask something..."))); ?>
|
||||
|
||||
<div class="contentForm_options">
|
||||
<?php echo Html::textArea("answersText", "", array('id' => "contentForm_answersText", 'rows' => '5', 'style' => 'height: auto !important;', "class" => "form-control contentForm", "tabindex" => "2", "placeholder" => Yii::t('PollsModule.widgets_views_pollForm', "Possible answers (one per line)"))); ?>
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<?php echo Html::checkbox("allowMultiple", "", array('id' => "contentForm_allowMultiple", 'class' => 'checkbox contentForm', "tabindex" => "4")); ?> <?php echo Yii::t('PollsModule.widgets_views_pollForm', 'Allow multiple answers per user?'); ?>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
```
|
||||
|
||||
### Create Action
|
||||
|
||||
Create an action in your modules controller to receive form inputs.
|
||||
|
||||
All default tasks (e.g. access validation, ContentContainer assignment) are handled by [[humhub\modules\content\widgets\WallCreateContentForm::create]]
|
||||
|
||||
|
||||
Example:
|
||||
|
||||
```php
|
||||
|
||||
public function actionCreate()
|
||||
{
|
||||
$poll = new Poll();
|
||||
$poll->question = Yii::$app->request->post('question');
|
||||
$poll->answersText = Yii::$app->request->post('answersText');
|
||||
$poll->allow_multiple = Yii::$app->request->post('allowMultiple', 0);
|
||||
|
||||
return \humhub\modules\polls\widgets\WallCreateForm::create($poll);
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
### Display Form
|
||||
|
||||
Place the Form widget above the Stream widget in your view.
|
||||
|
||||
e.g.
|
||||
|
||||
```php
|
||||
|
||||
<?php echo \humhub\modules\polls\widgets\WallCreateForm::widget(array('contentContainer' => $contentContainer)); ?>
|
||||
|
||||
```
|
||||
|
21
protected/humhub/docs/guide/dev-testing.md
Normal file
21
protected/humhub/docs/guide/dev-testing.md
Normal file
@ -0,0 +1,21 @@
|
||||
Testing
|
||||
====================
|
||||
|
||||
1. Install codeception
|
||||
composer global require "codeception/codeception=2.0.*" "codeception/specify=*" "codeception/verify=*"
|
||||
|
||||
2. Create test Database:
|
||||
CREATE DATABASE `humhub_test` CHARACTER SET utf8 COLLATE utf8_general_ci;
|
||||
|
||||
3. Migrate Up:
|
||||
cd protected/humhub/tests/codeception/bin
|
||||
php yii migrate/up --includeModuleMigrations=1 --interactive=0
|
||||
php yii installer/auto
|
||||
|
||||
4. Build Tests:
|
||||
cd protected/humhub/tests
|
||||
codecept build
|
||||
|
||||
5. Run Tests:
|
||||
cd protected/humhub/tests/
|
||||
codecept run
|
88
protected/humhub/docs/guide/dev-widgets.md
Normal file
88
protected/humhub/docs/guide/dev-widgets.md
Normal file
@ -0,0 +1,88 @@
|
||||
Widgets
|
||||
============
|
||||
|
||||
Widgets are used to provide reusable view parts by means of a view class. Please refer to the [Yii-Guide](http://www.yiiframework.com/doc-2.0/guide-structure-widgets.html)
|
||||
for more information about widgets.
|
||||
|
||||
## Widget Stacks
|
||||
|
||||
HumHub uses Widget-Stacks to assamble multiple entries of a base widget as a naviagation or list.
|
||||
Stacked widget are derived from [[humhub\widgets\BaseStack]] and will fire an `onInit` and `onRun` event by default,
|
||||
which can be subscribed by other modules to inject widget items. This mechanism can be used for example for sidebars.
|
||||
|
||||
Example of stack used as sidebar:
|
||||
|
||||
```php
|
||||
<?php
|
||||
// Render the sidebar with two default item
|
||||
echo \humhub\core\space\widgets\Sidebar::widget(['widgets' => [
|
||||
[\humhub\core\activity\widgets\Stream::className(), ['streamAction' => '/space/space/stream', 'contentContainer' => $space], ['sortOrder' => 10]],
|
||||
[\humhub\core\space\widgets\Members::className(), ['space' => $space], ['sortOrder' => 20]]
|
||||
]]);
|
||||
?>
|
||||
```
|
||||
|
||||
__config.php__
|
||||
|
||||
```php
|
||||
// Subscribe to the onInit event of the sidebar
|
||||
'events' => array(
|
||||
// Wait for TopMenu Initalization Event
|
||||
array('class' => 'DashboardSidebarWidget', 'event' => 'onInit', 'callback' => array('ExampleModule', 'onDashboardSidebarInit')),
|
||||
),
|
||||
//...
|
||||
```
|
||||
|
||||
__Events.php__
|
||||
|
||||
```php
|
||||
// This handler function will inject a custom widget to the stack
|
||||
public static function onDashboardSidebarInit($event) {
|
||||
$event->sender->addWidget('application.modules.example.widgets.MyCoolWidget', array(), array('sortOrder' => 1));
|
||||
}
|
||||
```
|
||||
|
||||
## Menus
|
||||
|
||||
All navigations widget classes inherit from the class [[humhub\widgets\BaseMenu]], which allows modules
|
||||
to inject own items into navigation menu.
|
||||
|
||||
Example:
|
||||
|
||||
__config.php__ - Catching Event
|
||||
|
||||
```php
|
||||
use humhub\widgets\TopMenu;
|
||||
|
||||
return [
|
||||
//...
|
||||
'events' => [
|
||||
['class' => TopMenu::className(), 'event' => TopMenu::EVENT_INIT, 'callback' => ['humhub\modules\calendar\Events', 'onTopMenuInit']],
|
||||
],
|
||||
]
|
||||
```
|
||||
|
||||
|
||||
__Events.php__ - Handling the Event
|
||||
|
||||
```php
|
||||
//...
|
||||
public static function onTopMenuInit($event)
|
||||
{
|
||||
if (Yii::$app->user->isGuest) {
|
||||
return;
|
||||
}
|
||||
|
||||
$user = Yii::$app->user->getIdentity();
|
||||
if ($user->isModuleEnabled('calendar')) {
|
||||
$event->sender->addItem([
|
||||
'label' => Yii::t('CalendarModule.base', 'Calendar'),
|
||||
'url' => Url::to(['/calendar/global/index']),
|
||||
'icon' => '<i class="fa fa-calendar"></i>',
|
||||
'isActive' => (Yii::$app->controller->module && Yii::$app->controller->module->id == 'calendar' && Yii::$app->controller->id == 'global'),
|
||||
'sortOrder' => 300,
|
||||
]);
|
||||
}
|
||||
}
|
||||
//...
|
||||
```
|
@ -1,110 +0,0 @@
|
||||
Space
|
||||
=====
|
||||
|
||||
When your module should also appear in space module section you need to add the
|
||||
SpaceModuleBehavior to your Module Class.
|
||||
|
||||
```php
|
||||
|
||||
class SomeModule extends HWebModule
|
||||
{
|
||||
|
||||
public function behaviors()
|
||||
{
|
||||
|
||||
return array(
|
||||
'SpaceModuleBehavior' => array(
|
||||
'class' => 'application.modules_core.space.behaviors.SpaceModuleBehavior',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
//...
|
||||
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
See SpaceModuleBehavior Class for further details.
|
||||
|
||||
## Example: Add item to space navigation
|
||||
|
||||
Catch Space Navigation Init Event in your modules autostart.php.
|
||||
|
||||
```autostart.php
|
||||
|
||||
Yii::app()->moduleManager->register(array(
|
||||
//...
|
||||
|
||||
'events' => array(
|
||||
array('class' => 'SpaceMenuWidget', 'event' => 'onInit', 'callback' => array('ExampleModule', 'onSpaceMenuInit')),
|
||||
)
|
||||
|
||||
));
|
||||
|
||||
```
|
||||
|
||||
Define callback in your module to add item.
|
||||
|
||||
```php
|
||||
/**
|
||||
* On build of a Space Navigation, check if this module is enabled.
|
||||
* When enabled add a menu item
|
||||
*
|
||||
* @param type $event
|
||||
*/
|
||||
public static function onSpaceMenuInit($event) {
|
||||
|
||||
$space = Yii::app()->getController()->getSpace();
|
||||
|
||||
// Is Module enabled on this workspace?
|
||||
if ($space->isModuleEnabled('example')) {
|
||||
|
||||
$event->sender->addItem(array(
|
||||
'label' => 'Some space navigation entry',
|
||||
'url' => '#',
|
||||
'icon' => 'icon',
|
||||
'isActive' => (Yii::app()->controller->module && Yii::app()->controller->module->id == 'example'),
|
||||
));
|
||||
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## Access space by by module controller
|
||||
|
||||
By adding the SpaceControllerBehavior you are able to access current space in your controllers.
|
||||
Make sure you always pass the current space guid (sguid) in your urls.
|
||||
|
||||
When using the method createContainerUrl (provided by SpaceControllerBehavior or UserControllerBehavior) the
|
||||
current space or user guid is automatically added to urls.
|
||||
|
||||
```php
|
||||
|
||||
/**
|
||||
* Add mix-ins to this model
|
||||
*
|
||||
* @return type
|
||||
*/
|
||||
public function behaviors()
|
||||
{
|
||||
return array(
|
||||
'SpaceControllerBehavior' => array(
|
||||
'class' => 'application.modules_core.space.behaviors.SpaceControllerBehavior',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
public function actionTest() {
|
||||
$currentSpace = $this->getSpace();
|
||||
|
||||
$this->redirect($this->createContainerUrl('test2'));
|
||||
|
||||
}
|
||||
|
||||
public function actionTest2() {
|
||||
$currentSpace = $this->getSpace();
|
||||
}
|
||||
|
||||
```
|
@ -1,4 +0,0 @@
|
||||
User
|
||||
====
|
||||
|
||||
TBD
|
Binary file not shown.
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 46 KiB |
91
protected/humhub/docs/guide/images/notificationClassDiag.svg
Normal file
91
protected/humhub/docs/guide/images/notificationClassDiag.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 53 KiB |
@ -2,12 +2,26 @@
|
||||
|
||||
Here you will learn how you can adapt existing themes to working fine with actually versions.
|
||||
|
||||
## Migrate to 1.0.0-beta.4
|
||||
## Migrate to 1.1
|
||||
|
||||
- Make sure to update your themed less file with the latest version.
|
||||
In the upcoming 1.2.x releases we'll split the 'theme' less file into multiple files, to simplify this process.
|
||||
|
||||
- There were also many view file updates this release, please check changes (e.g. diff) of your themed versions.
|
||||
We are constantly reducing view complexity to ease this process.
|
||||
|
||||
**Important changed views:**
|
||||
|
||||
- Logins (Standalone / Modal)
|
||||
- Registration
|
||||
- Main Layout
|
||||
|
||||
## Migrate from 0.20 to 1.0
|
||||
|
||||
The following line was added to the HumHub Base Theme Less/Css file due to a Bootstrap update:
|
||||
https://github.com/humhub/humhub/blob/0a388d225a53fd873773cf0989d6e10aaf66996a/themes/HumHub/css/theme.less#L648
|
||||
|
||||
## Migrate from 0.11.x to 0.20
|
||||
## Migrate from 0.11 to 0.20
|
||||
|
||||
As you know, HumHub based on the Yii Framework. In the new 0.20 release, the Framework was changed from Yii 1.1 to Yii 2. With this change the style.css in **webroot/css/** was removed and from now all styles are merged in the theme.css under **webroot/themes/humhub/css/**.
|
||||
|
||||
@ -32,10 +46,7 @@ Follow this steps to migrate an older theme ot 0.20:
|
||||
|
||||
6. Check if everything works well, and fix optical issues at your theme file, if necessery.
|
||||
|
||||
|
||||
---
|
||||
|
||||
## Migrate from 0.9 and earlier to 10.0
|
||||
## Migrate from 0.9 to 10.0
|
||||
|
||||
In 0.10 release, all refer links from **head.php** (to js, css and icon files) moved back to the ``<head>`` section in **main.php**, to keep them independet from themes.
|
||||
|
||||
|
169
protected/humhub/libs/BaseSettingsManager.php
Normal file
169
protected/humhub/libs/BaseSettingsManager.php
Normal file
@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\libs;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Component;
|
||||
|
||||
/**
|
||||
* Description of SettingManager
|
||||
*
|
||||
* @since 1.1
|
||||
* @author Luke
|
||||
*/
|
||||
abstract class BaseSettingsManager extends Component
|
||||
{
|
||||
|
||||
/**
|
||||
* @var string module id this settings manager belongs to.
|
||||
*/
|
||||
public $moduleId = null;
|
||||
|
||||
/**
|
||||
* @var array|null of loaded settings
|
||||
*/
|
||||
protected $_loaded = null;
|
||||
|
||||
/**
|
||||
* @var string settings model class name
|
||||
*/
|
||||
public $modelClass = 'humhub\models\Setting';
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if ($this->moduleId === null) {
|
||||
throw new \Exception('Could not determine module id');
|
||||
}
|
||||
|
||||
$this->loadValues();
|
||||
|
||||
parent::init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a settings value
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
*/
|
||||
public function set($name, $value)
|
||||
{
|
||||
if ($value === null) {
|
||||
return $this->delete($name);
|
||||
}
|
||||
|
||||
// Update database setting record
|
||||
$record = $this->find()->andWhere(['name' => $name])->one();
|
||||
if ($record === null) {
|
||||
$record = $this->createRecord();
|
||||
$record->name = $name;
|
||||
}
|
||||
$record->value = (string) $value;
|
||||
if (!$record->save()) {
|
||||
throw new \yii\base\Exception("Could not store setting! (" . print_r($record->getErrors(), 1) . ")");
|
||||
}
|
||||
|
||||
// Store to runtime
|
||||
$this->_loaded[$name] = $value;
|
||||
|
||||
$this->invalidateCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns value of setting
|
||||
*
|
||||
* @param string $name the name of setting
|
||||
* @return string the setting value or null when not exists
|
||||
*/
|
||||
public function get($name)
|
||||
{
|
||||
return isset($this->_loaded[$name]) ? $this->_loaded[$name] : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes setting
|
||||
*
|
||||
* @param string $name
|
||||
*/
|
||||
public function delete($name)
|
||||
{
|
||||
$record = $this->find()->andWhere(['name' => $name])->one();
|
||||
if ($record !== null) {
|
||||
$record->delete();
|
||||
}
|
||||
|
||||
if (isset($this->_loaded[$name])) {
|
||||
unset($this->_loaded[$name]);
|
||||
}
|
||||
$this->invalidateCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads values from database
|
||||
*/
|
||||
protected function loadValues()
|
||||
{
|
||||
$cached = Yii::$app->cache->get($this->getCacheKey());
|
||||
if ($cached === false) {
|
||||
$this->_loaded = [];
|
||||
$settings = &$this->_loaded;
|
||||
|
||||
array_map(function ($record) use(&$settings ) {
|
||||
$settings[$record->name] = $record->value;
|
||||
}, $this->find()->all());
|
||||
|
||||
Yii::$app->cache->set($this->getCacheKey(), $this->_loaded);
|
||||
} else {
|
||||
$this->_loaded = $cached;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Invalidates settings cache
|
||||
*/
|
||||
protected function invalidateCache()
|
||||
{
|
||||
Yii::$app->cache->delete($this->getCacheKey());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns settings managers cache key
|
||||
*
|
||||
* @return string the cache key
|
||||
*/
|
||||
protected function getCacheKey()
|
||||
{
|
||||
return 'settings-' . $this->moduleId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns settings active record instance
|
||||
*/
|
||||
protected function createRecord()
|
||||
{
|
||||
$model = new $this->modelClass;
|
||||
$model->module_id = $this->moduleId;
|
||||
return $model;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns ActiveQuery to find settings
|
||||
*
|
||||
* @return \yii\db\ActiveQuery
|
||||
*/
|
||||
protected function find()
|
||||
{
|
||||
$modelClass = $this->modelClass;
|
||||
return $modelClass::find()->andWhere(['module_id' => $this->moduleId]);
|
||||
}
|
||||
|
||||
}
|
@ -21,7 +21,7 @@ class CURLHelper
|
||||
|
||||
/**
|
||||
* Returns CURL Default Options
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function getOptions()
|
||||
@ -34,17 +34,17 @@ class CURLHelper
|
||||
CURLOPT_CAINFO => Yii::getAlias('@humhub/config/cacert.pem')
|
||||
);
|
||||
|
||||
if (Setting::Get('enabled', 'proxy')) {
|
||||
$options[CURLOPT_PROXY] = Setting::Get('server', 'proxy');
|
||||
$options[CURLOPT_PROXYPORT] = Setting::Get('port', 'proxy');
|
||||
if (Yii::$app->settings->get('proxy.enabled')) {
|
||||
$options[CURLOPT_PROXY] = Yii::$app->settings->get('proxy.server');
|
||||
$options[CURLOPT_PROXYPORT] = Yii::$app->settings->get('proxy.port');
|
||||
if (defined('CURLOPT_PROXYUSERNAME')) {
|
||||
$options[CURLOPT_PROXYUSERNAME] = Setting::Get('user', 'proxy');
|
||||
$options[CURLOPT_PROXYUSERNAME] = Yii::$app->settings->get('proxy.user');
|
||||
}
|
||||
if (defined('CURLOPT_PROXYPASSWORD')) {
|
||||
$options[CURLOPT_PROXYPASSWORD] = Setting::Get('password', 'proxy');
|
||||
$options[CURLOPT_PROXYPASSWORD] = Yii::$app->settings->get('proxy.password');
|
||||
}
|
||||
if (defined('CURLOPT_NOPROXY')) {
|
||||
$options[CURLOPT_NOPROXY] = Setting::Get('noproxy', 'proxy');
|
||||
$options[CURLOPT_NOPROXY] = Yii::$app->settings->get('proxy.noproxy');
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -10,7 +10,7 @@ namespace humhub\libs;
|
||||
|
||||
use Yii;
|
||||
use yii\helpers\ArrayHelper;
|
||||
use humhub\components\Theme;
|
||||
use humhub\libs\ThemeHelper;
|
||||
use humhub\models\Setting;
|
||||
|
||||
/**
|
||||
@ -23,7 +23,7 @@ class DynamicConfig extends \yii\base\Object
|
||||
|
||||
/**
|
||||
* Add an array to the dynamic configuration
|
||||
*
|
||||
*
|
||||
* @param array $new
|
||||
*/
|
||||
public static function merge($new)
|
||||
@ -32,54 +32,9 @@ class DynamicConfig extends \yii\base\Object
|
||||
self::save($config);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when a a setting is changed.
|
||||
*
|
||||
* @see Setting
|
||||
* @param Setting $setting
|
||||
*/
|
||||
public static function onSettingChange($setting)
|
||||
{
|
||||
$config = self::load();
|
||||
self::setSettingValue($config['params'], $setting);
|
||||
self::save($config);
|
||||
}
|
||||
|
||||
public static function setSettingValue(&$config, $setting)
|
||||
{
|
||||
|
||||
$moduleId = $setting->module_id;
|
||||
if ($moduleId == '') {
|
||||
$moduleId = 'core';
|
||||
}
|
||||
|
||||
$value = '';
|
||||
if ($setting->value_text != '') {
|
||||
$value = (string) $setting->value_text;
|
||||
} else {
|
||||
$value = (string) $setting->value;
|
||||
}
|
||||
|
||||
$config['settings'][$moduleId][$setting->name] = $value;
|
||||
Yii::$app->params['settings'][$moduleId][$setting->name] = $value;
|
||||
}
|
||||
|
||||
public static function getSettingValue($name, $moduleId)
|
||||
{
|
||||
if ($moduleId == '') {
|
||||
$moduleId = 'core';
|
||||
}
|
||||
|
||||
if (isset(Yii::$app->params['settings'][$moduleId][$name])) {
|
||||
return Yii::$app->params['settings'][$moduleId][$name];
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the dynamic configuration
|
||||
*
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public static function load()
|
||||
@ -103,7 +58,7 @@ class DynamicConfig extends \yii\base\Object
|
||||
|
||||
/**
|
||||
* Sets a new dynamic configuration
|
||||
*
|
||||
*
|
||||
* @param array $config
|
||||
*/
|
||||
public static function save($config)
|
||||
@ -135,17 +90,17 @@ class DynamicConfig extends \yii\base\Object
|
||||
$config = self::load();
|
||||
|
||||
// Add Application Name to Configuration
|
||||
$config['name'] = Setting::Get('name');
|
||||
$config['name'] = Yii::$app->settings->get('name');
|
||||
|
||||
// Add Default language
|
||||
$defaultLanguage = Setting::Get('defaultLanguage');
|
||||
$defaultLanguage = Yii::$app->settings->get('defaultLanguage');
|
||||
if ($defaultLanguage !== null && $defaultLanguage != "") {
|
||||
$config['language'] = Setting::Get('defaultLanguage');
|
||||
$config['language'] = Yii::$app->settings->get('defaultLanguage');
|
||||
} else {
|
||||
$config['language'] = Yii::$app->language;
|
||||
}
|
||||
|
||||
$timeZone = Setting::Get('timeZone');
|
||||
$timeZone = Yii::$app->settings->get('timeZone');
|
||||
if ($timeZone != "") {
|
||||
$config['timeZone'] = $timeZone;
|
||||
$config['components']['formatter']['defaultTimeZone'] = $timeZone;
|
||||
@ -154,66 +109,55 @@ class DynamicConfig extends \yii\base\Object
|
||||
}
|
||||
|
||||
// Add Caching
|
||||
$cacheClass = Setting::Get('type', 'cache');
|
||||
$cacheClass = Yii::$app->settings->get('cache.class');
|
||||
if (in_array($cacheClass, ['yii\caching\DummyCache', 'yii\caching\ApcCache', 'yii\caching\FileCache'])) {
|
||||
$config['components']['cache'] = [
|
||||
'class' => $cacheClass,
|
||||
'keyPrefix' => Yii::$app->id
|
||||
];
|
||||
|
||||
// Prefix APC Cache Keys
|
||||
//if ($cacheClass == 'yii\caching\ApcCache') {
|
||||
// $config['components']['cache'] = [
|
||||
// 'keyPrefix' => Yii::$app->id
|
||||
// ];
|
||||
//}
|
||||
}
|
||||
// Add User settings
|
||||
$config['components']['user'] = array();
|
||||
if (Setting::Get('defaultUserIdleTimeoutSec', 'authentication_internal')) {
|
||||
$config['components']['user']['authTimeout'] = Setting::Get('defaultUserIdleTimeoutSec', 'authentication_internal');
|
||||
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();
|
||||
if (Setting::Get('transportType', 'mailing') == 'smtp') {
|
||||
if (Yii::$app->settings->get('mailer.transportType') == 'smtp') {
|
||||
$mail['transport']['class'] = 'Swift_SmtpTransport';
|
||||
|
||||
if (Setting::Get('hostname', 'mailing'))
|
||||
$mail['transport']['host'] = Setting::Get('hostname', 'mailing');
|
||||
if (Yii::$app->settings->get('mailer.hostname'))
|
||||
$mail['transport']['host'] = Yii::$app->settings->get('mailer.hostname');
|
||||
|
||||
if (Setting::Get('username', 'mailing'))
|
||||
$mail['transport']['username'] = Setting::Get('username', 'mailing');
|
||||
if (Yii::$app->settings->get('mailer.username'))
|
||||
$mail['transport']['username'] = Yii::$app->settings->get('mailer.username');
|
||||
|
||||
if (Setting::Get('password', 'mailing'))
|
||||
$mail['transport']['password'] = Setting::Get('password', 'mailing');
|
||||
if (Yii::$app->settings->get('mailer.password'))
|
||||
$mail['transport']['password'] = Yii::$app->settings->get('mailer.password');
|
||||
|
||||
if (Setting::Get('encryption', 'mailing'))
|
||||
$mail['transport']['encryption'] = Setting::Get('encryption', 'mailing');
|
||||
if (Yii::$app->settings->get('mailer.encryption'))
|
||||
$mail['transport']['encryption'] = Yii::$app->settings->get('mailer.encryption');
|
||||
|
||||
if (Setting::Get('port', 'mailing'))
|
||||
$mail['transport']['port'] = Setting::Get('port', 'mailing');
|
||||
if (Yii::$app->settings->get('mailer.port'))
|
||||
$mail['transport']['port'] = Yii::$app->settings->get('mailer.port');
|
||||
|
||||
/*
|
||||
if (Setting::Get('allowSelfSignedCerts', 'mailing')) {
|
||||
if (Yii::$app->settings->get('mailer.allowSelfSignedCerts')) {
|
||||
$mail['transport']['ssl']['allow_self_signed'] = true;
|
||||
$mail['transport']['ssl']['verify_peer'] = false;
|
||||
}
|
||||
*/
|
||||
} elseif (Setting::Get('transportType', 'mailing') == 'php') {
|
||||
} elseif (Yii::$app->settings->get('mailer.transportType') == 'php') {
|
||||
$mail['transport']['class'] = 'Swift_MailTransport';
|
||||
} else {
|
||||
$mail['useFileTransport'] = true;
|
||||
}
|
||||
$config['components']['mailer'] = $mail;
|
||||
$config = ArrayHelper::merge($config, Theme::getThemeConfig(Setting::Get('theme')));
|
||||
$config = ArrayHelper::merge($config, ThemeHelper::getThemeConfig(Yii::$app->settings->get('theme')));
|
||||
$config['params']['config_created_at'] = time();
|
||||
|
||||
foreach (Setting::find()->all() as $setting) {
|
||||
self::setSettingValue($config['params'], $setting);
|
||||
}
|
||||
|
||||
self::save($config);
|
||||
}
|
||||
|
||||
|
@ -513,289 +513,9 @@ class iso3166Codes
|
||||
"ZW" => "263"
|
||||
);
|
||||
|
||||
public static $continents = array(
|
||||
"AF" => "Africa",
|
||||
"AN" => "Antarctica",
|
||||
"AS" => "Asia",
|
||||
"EU" => "Europa",
|
||||
"NA" => "North America",
|
||||
"OC" => "Oceania",
|
||||
"SA" => "South America"
|
||||
);
|
||||
|
||||
/**
|
||||
* Trigger Yii translations.
|
||||
* Only used for the message/create command from YII.
|
||||
*/
|
||||
public static function initTranslation()
|
||||
{
|
||||
static::$countriesTranslated = array(
|
||||
'AF' => Yii::t('iso3166Codes', 'Afghanistan'),
|
||||
'AX' => Yii::t('iso3166Codes', 'Aland Islands'),
|
||||
'AL' => Yii::t('iso3166Codes', 'Albania'),
|
||||
'DZ' => Yii::t('iso3166Codes', 'Algeria'),
|
||||
'AS' => Yii::t('iso3166Codes', 'American Samoa'),
|
||||
'AD' => Yii::t('iso3166Codes', 'Andorra'),
|
||||
'AO' => Yii::t('iso3166Codes', 'Angola'),
|
||||
'AI' => Yii::t('iso3166Codes', 'Anguilla'),
|
||||
'AQ' => Yii::t('iso3166Codes', 'Antarctica'),
|
||||
'AG' => Yii::t('iso3166Codes', 'Antigua and Barbuda'),
|
||||
'AR' => Yii::t('iso3166Codes', 'Argentina'),
|
||||
'AM' => Yii::t('iso3166Codes', 'Armenia'),
|
||||
'AW' => Yii::t('iso3166Codes', 'Aruba'),
|
||||
'AU' => Yii::t('iso3166Codes', 'Australia'),
|
||||
'AT' => Yii::t('iso3166Codes', 'Austria'),
|
||||
'AZ' => Yii::t('iso3166Codes', 'Azerbaijan'),
|
||||
'BS' => Yii::t('iso3166Codes', 'Bahamas'),
|
||||
'BH' => Yii::t('iso3166Codes', 'Bahrain'),
|
||||
'BD' => Yii::t('iso3166Codes', 'Bangladesh'),
|
||||
'BB' => Yii::t('iso3166Codes', 'Barbados'),
|
||||
'BY' => Yii::t('iso3166Codes', 'Belarus'),
|
||||
'BE' => Yii::t('iso3166Codes', 'Belgium'),
|
||||
'BZ' => Yii::t('iso3166Codes', 'Belize'),
|
||||
'BJ' => Yii::t('iso3166Codes', 'Benin'),
|
||||
'BM' => Yii::t('iso3166Codes', 'Bermuda'),
|
||||
'BT' => Yii::t('iso3166Codes', 'Bhutan'),
|
||||
'BO' => Yii::t('iso3166Codes', 'Bolivia'),
|
||||
'BQ' => Yii::t('iso3166Codes', 'Bonaire, Saint Eustatius and Saba'),
|
||||
'BA' => Yii::t('iso3166Codes', 'Bosnia and Herzegovina'),
|
||||
'BW' => Yii::t('iso3166Codes', 'Botswana'),
|
||||
'BV' => Yii::t('iso3166Codes', 'Bouvet Island'),
|
||||
'BR' => Yii::t('iso3166Codes', 'Brazil'),
|
||||
'IO' => Yii::t('iso3166Codes', 'British Indian Ocean Territory'),
|
||||
'VG' => Yii::t('iso3166Codes', 'British Virgin Islands'),
|
||||
'BN' => Yii::t('iso3166Codes', 'Brunei'),
|
||||
'BG' => Yii::t('iso3166Codes', 'Bulgaria'),
|
||||
'BF' => Yii::t('iso3166Codes', 'Burkina Faso'),
|
||||
'BI' => Yii::t('iso3166Codes', 'Burundi'),
|
||||
'KH' => Yii::t('iso3166Codes', 'Cambodia'),
|
||||
'CM' => Yii::t('iso3166Codes', 'Cameroon'),
|
||||
'CA' => Yii::t('iso3166Codes', 'Canada'),
|
||||
'CV' => Yii::t('iso3166Codes', 'Cape Verde'),
|
||||
'KY' => Yii::t('iso3166Codes', 'Cayman Islands'),
|
||||
'CF' => Yii::t('iso3166Codes', 'Central African Republic'),
|
||||
'TD' => Yii::t('iso3166Codes', 'Chad'),
|
||||
'CL' => Yii::t('iso3166Codes', 'Chile'),
|
||||
'CN' => Yii::t('iso3166Codes', 'China'),
|
||||
'CX' => Yii::t('iso3166Codes', 'Christmas Island'),
|
||||
'CC' => Yii::t('iso3166Codes', 'Cocos Islands'),
|
||||
'CO' => Yii::t('iso3166Codes', 'Colombia'),
|
||||
'KM' => Yii::t('iso3166Codes', 'Comoros'),
|
||||
'CK' => Yii::t('iso3166Codes', 'Cook Islands'),
|
||||
'CR' => Yii::t('iso3166Codes', 'Costa Rica'),
|
||||
'HR' => Yii::t('iso3166Codes', 'Croatia'),
|
||||
'CU' => Yii::t('iso3166Codes', 'Cuba'),
|
||||
'CW' => Yii::t('iso3166Codes', 'Curacao'),
|
||||
'CY' => Yii::t('iso3166Codes', 'Cyprus'),
|
||||
'CZ' => Yii::t('iso3166Codes', 'Czech Republic'),
|
||||
'CD' => Yii::t('iso3166Codes', 'Democratic Republic of the Congo'),
|
||||
'DK' => Yii::t('iso3166Codes', 'Denmark'),
|
||||
'DJ' => Yii::t('iso3166Codes', 'Djibouti'),
|
||||
'DM' => Yii::t('iso3166Codes', 'Dominica'),
|
||||
'DO' => Yii::t('iso3166Codes', 'Dominican Republic'),
|
||||
'EC' => Yii::t('iso3166Codes', 'Ecuador'),
|
||||
'EG' => Yii::t('iso3166Codes', 'Egypt'),
|
||||
'SV' => Yii::t('iso3166Codes', 'El Salvador'),
|
||||
'GQ' => Yii::t('iso3166Codes', 'Equatorial Guinea'),
|
||||
'ER' => Yii::t('iso3166Codes', 'Eritrea'),
|
||||
'EE' => Yii::t('iso3166Codes', 'Estonia'),
|
||||
'ET' => Yii::t('iso3166Codes', 'Ethiopia'),
|
||||
'FK' => Yii::t('iso3166Codes', 'Falkland Islands'),
|
||||
'FO' => Yii::t('iso3166Codes', 'Faroe Islands'),
|
||||
'FJ' => Yii::t('iso3166Codes', 'Fiji'),
|
||||
'FI' => Yii::t('iso3166Codes', 'Finland'),
|
||||
'FR' => Yii::t('iso3166Codes', 'France'),
|
||||
'GF' => Yii::t('iso3166Codes', 'French Guiana'),
|
||||
'PF' => Yii::t('iso3166Codes', 'French Polynesia'),
|
||||
'TF' => Yii::t('iso3166Codes', 'French Southern Territories'),
|
||||
'GA' => Yii::t('iso3166Codes', 'Gabon'),
|
||||
'GM' => Yii::t('iso3166Codes', 'Gambia'),
|
||||
'GE' => Yii::t('iso3166Codes', 'Georgia'),
|
||||
'DE' => Yii::t('iso3166Codes', 'Germany'),
|
||||
'GH' => Yii::t('iso3166Codes', 'Ghana'),
|
||||
'GI' => Yii::t('iso3166Codes', 'Gibraltar'),
|
||||
'GR' => Yii::t('iso3166Codes', 'Greece'),
|
||||
'GL' => Yii::t('iso3166Codes', 'Greenland'),
|
||||
'GD' => Yii::t('iso3166Codes', 'Grenada'),
|
||||
'GP' => Yii::t('iso3166Codes', 'Guadeloupe'),
|
||||
'GU' => Yii::t('iso3166Codes', 'Guam'),
|
||||
'GT' => Yii::t('iso3166Codes', 'Guatemala'),
|
||||
'GG' => Yii::t('iso3166Codes', 'Guernsey'),
|
||||
'GN' => Yii::t('iso3166Codes', 'Guinea'),
|
||||
'GW' => Yii::t('iso3166Codes', 'Guinea-Bissau'),
|
||||
'GY' => Yii::t('iso3166Codes', 'Guyana'),
|
||||
'HT' => Yii::t('iso3166Codes', 'Haiti'),
|
||||
'HM' => Yii::t('iso3166Codes', 'Heard Island and McDonald Islands'),
|
||||
'HN' => Yii::t('iso3166Codes', 'Honduras'),
|
||||
'HK' => Yii::t('iso3166Codes', 'Hong Kong'),
|
||||
'HU' => Yii::t('iso3166Codes', 'Hungary'),
|
||||
'IS' => Yii::t('iso3166Codes', 'Iceland'),
|
||||
'IN' => Yii::t('iso3166Codes', 'India'),
|
||||
'ID' => Yii::t('iso3166Codes', 'Indonesia'),
|
||||
'IR' => Yii::t('iso3166Codes', 'Iran'),
|
||||
'IQ' => Yii::t('iso3166Codes', 'Iraq'),
|
||||
'IE' => Yii::t('iso3166Codes', 'Ireland'),
|
||||
'IM' => Yii::t('iso3166Codes', 'Isle of Man'),
|
||||
'IL' => Yii::t('iso3166Codes', 'Israel'),
|
||||
'IT' => Yii::t('iso3166Codes', 'Italy'),
|
||||
'CI' => Yii::t('iso3166Codes', 'Ivory Coast'),
|
||||
'JM' => Yii::t('iso3166Codes', 'Jamaica'),
|
||||
'JP' => Yii::t('iso3166Codes', 'Japan'),
|
||||
'JE' => Yii::t('iso3166Codes', 'Jersey'),
|
||||
'JO' => Yii::t('iso3166Codes', 'Jordan'),
|
||||
'KZ' => Yii::t('iso3166Codes', 'Kazakhstan'),
|
||||
'KE' => Yii::t('iso3166Codes', 'Kenya'),
|
||||
'KI' => Yii::t('iso3166Codes', 'Kiribati'),
|
||||
'XK' => Yii::t('iso3166Codes', 'Kosovo'),
|
||||
'KW' => Yii::t('iso3166Codes', 'Kuwait'),
|
||||
'KG' => Yii::t('iso3166Codes', 'Kyrgyzstan'),
|
||||
'LA' => Yii::t('iso3166Codes', 'Laos'),
|
||||
'LV' => Yii::t('iso3166Codes', 'Latvia'),
|
||||
'LB' => Yii::t('iso3166Codes', 'Lebanon'),
|
||||
'LS' => Yii::t('iso3166Codes', 'Lesotho'),
|
||||
'LR' => Yii::t('iso3166Codes', 'Liberia'),
|
||||
'LY' => Yii::t('iso3166Codes', 'Libya'),
|
||||
'LI' => Yii::t('iso3166Codes', 'Liechtenstein'),
|
||||
'LT' => Yii::t('iso3166Codes', 'Lithuania'),
|
||||
'LU' => Yii::t('iso3166Codes', 'Luxembourg'),
|
||||
'MO' => Yii::t('iso3166Codes', 'Macao'),
|
||||
'MK' => Yii::t('iso3166Codes', 'Macedonia'),
|
||||
'MG' => Yii::t('iso3166Codes', 'Madagascar'),
|
||||
'MW' => Yii::t('iso3166Codes', 'Malawi'),
|
||||
'MY' => Yii::t('iso3166Codes', 'Malaysia'),
|
||||
'MV' => Yii::t('iso3166Codes', 'Maldives'),
|
||||
'ML' => Yii::t('iso3166Codes', 'Mali'),
|
||||
'MT' => Yii::t('iso3166Codes', 'Malta'),
|
||||
'MH' => Yii::t('iso3166Codes', 'Marshall Islands'),
|
||||
'MQ' => Yii::t('iso3166Codes', 'Martinique'),
|
||||
'MR' => Yii::t('iso3166Codes', 'Mauritania'),
|
||||
'MU' => Yii::t('iso3166Codes', 'Mauritius'),
|
||||
'YT' => Yii::t('iso3166Codes', 'Mayotte'),
|
||||
'MX' => Yii::t('iso3166Codes', 'Mexico'),
|
||||
'FM' => Yii::t('iso3166Codes', 'Micronesia'),
|
||||
'MD' => Yii::t('iso3166Codes', 'Moldova'),
|
||||
'MC' => Yii::t('iso3166Codes', 'Monaco'),
|
||||
'MN' => Yii::t('iso3166Codes', 'Mongolia'),
|
||||
'ME' => Yii::t('iso3166Codes', 'Montenegro'),
|
||||
'MS' => Yii::t('iso3166Codes', 'Montserrat'),
|
||||
'MA' => Yii::t('iso3166Codes', 'Morocco'),
|
||||
'MZ' => Yii::t('iso3166Codes', 'Mozambique'),
|
||||
'MM' => Yii::t('iso3166Codes', 'Myanmar'),
|
||||
'NA' => Yii::t('iso3166Codes', 'Namibia'),
|
||||
'NR' => Yii::t('iso3166Codes', 'Nauru'),
|
||||
'NP' => Yii::t('iso3166Codes', 'Nepal'),
|
||||
'NL' => Yii::t('iso3166Codes', 'Netherlands'),
|
||||
'AN' => Yii::t('iso3166Codes', 'Netherlands Antilles'),
|
||||
'NC' => Yii::t('iso3166Codes', 'New Caledonia'),
|
||||
'NZ' => Yii::t('iso3166Codes', 'New Zealand'),
|
||||
'NI' => Yii::t('iso3166Codes', 'Nicaragua'),
|
||||
'NE' => Yii::t('iso3166Codes', 'Niger'),
|
||||
'NG' => Yii::t('iso3166Codes', 'Nigeria'),
|
||||
'NU' => Yii::t('iso3166Codes', 'Niue'),
|
||||
'NF' => Yii::t('iso3166Codes', 'Norfolk Island'),
|
||||
'KP' => Yii::t('iso3166Codes', 'North Korea'),
|
||||
'MP' => Yii::t('iso3166Codes', 'Northern Mariana Islands'),
|
||||
'NO' => Yii::t('iso3166Codes', 'Norway'),
|
||||
'OM' => Yii::t('iso3166Codes', 'Oman'),
|
||||
'PK' => Yii::t('iso3166Codes', 'Pakistan'),
|
||||
'PW' => Yii::t('iso3166Codes', 'Palau'),
|
||||
'PS' => Yii::t('iso3166Codes', 'Palestinian Territory'),
|
||||
'PA' => Yii::t('iso3166Codes', 'Panama'),
|
||||
'PG' => Yii::t('iso3166Codes', 'Papua New Guinea'),
|
||||
'PY' => Yii::t('iso3166Codes', 'Paraguay'),
|
||||
'PE' => Yii::t('iso3166Codes', 'Peru'),
|
||||
'PH' => Yii::t('iso3166Codes', 'Philippines'),
|
||||
'PN' => Yii::t('iso3166Codes', 'Pitcairn'),
|
||||
'PL' => Yii::t('iso3166Codes', 'Poland'),
|
||||
'PT' => Yii::t('iso3166Codes', 'Portugal'),
|
||||
'PR' => Yii::t('iso3166Codes', 'Puerto Rico'),
|
||||
'QA' => Yii::t('iso3166Codes', 'Qatar'),
|
||||
'CG' => Yii::t('iso3166Codes', 'Republic of the Congo'),
|
||||
'RE' => Yii::t('iso3166Codes', 'Reunion'),
|
||||
'RO' => Yii::t('iso3166Codes', 'Romania'),
|
||||
'RU' => Yii::t('iso3166Codes', 'Russia'),
|
||||
'RW' => Yii::t('iso3166Codes', 'Rwanda'),
|
||||
'BL' => Yii::t('iso3166Codes', 'Saint Barthelemy'),
|
||||
'SH' => Yii::t('iso3166Codes', 'Saint Helena'),
|
||||
'KN' => Yii::t('iso3166Codes', 'Saint Kitts and Nevis'),
|
||||
'LC' => Yii::t('iso3166Codes', 'Saint Lucia'),
|
||||
'MF' => Yii::t('iso3166Codes', 'Saint Martin'),
|
||||
'PM' => Yii::t('iso3166Codes', 'Saint Pierre and Miquelon'),
|
||||
'VC' => Yii::t('iso3166Codes', 'Saint Vincent and the Grenadines'),
|
||||
'WS' => Yii::t('iso3166Codes', 'Samoa'),
|
||||
'SM' => Yii::t('iso3166Codes', 'San Marino'),
|
||||
'ST' => Yii::t('iso3166Codes', 'Sao Tome and Principe'),
|
||||
'SA' => Yii::t('iso3166Codes', 'Saudi Arabia'),
|
||||
'SN' => Yii::t('iso3166Codes', 'Senegal'),
|
||||
'RS' => Yii::t('iso3166Codes', 'Serbia'),
|
||||
'SC' => Yii::t('iso3166Codes', 'Seychelles'),
|
||||
'SL' => Yii::t('iso3166Codes', 'Sierra Leone'),
|
||||
'SG' => Yii::t('iso3166Codes', 'Singapore'),
|
||||
'SX' => Yii::t('iso3166Codes', 'Sint Maarten'),
|
||||
'SK' => Yii::t('iso3166Codes', 'Slovakia'),
|
||||
'SI' => Yii::t('iso3166Codes', 'Slovenia'),
|
||||
'SB' => Yii::t('iso3166Codes', 'Solomon Islands'),
|
||||
'SO' => Yii::t('iso3166Codes', 'Somalia'),
|
||||
'ZA' => Yii::t('iso3166Codes', 'South Africa'),
|
||||
'GS' => Yii::t('iso3166Codes', 'South Georgia and the South Sandwich Islands'),
|
||||
'KR' => Yii::t('iso3166Codes', 'South Korea'),
|
||||
'SS' => Yii::t('iso3166Codes', 'South Sudan'),
|
||||
'ES' => Yii::t('iso3166Codes', 'Spain'),
|
||||
'LK' => Yii::t('iso3166Codes', 'Sri Lanka'),
|
||||
'SD' => Yii::t('iso3166Codes', 'Sudan'),
|
||||
'SR' => Yii::t('iso3166Codes', 'Suriname'),
|
||||
'SJ' => Yii::t('iso3166Codes', 'Svalbard and Jan Mayen'),
|
||||
'SZ' => Yii::t('iso3166Codes', 'Swaziland'),
|
||||
'SE' => Yii::t('iso3166Codes', 'Sweden'),
|
||||
'CH' => Yii::t('iso3166Codes', 'Switzerland'),
|
||||
'SY' => Yii::t('iso3166Codes', 'Syria'),
|
||||
'TW' => Yii::t('iso3166Codes', 'Taiwan'),
|
||||
'TJ' => Yii::t('iso3166Codes', 'Tajikistan'),
|
||||
'TZ' => Yii::t('iso3166Codes', 'Tanzania'),
|
||||
'TH' => Yii::t('iso3166Codes', 'Thailand'),
|
||||
'TL' => Yii::t('iso3166Codes', 'Timor-Leste'),
|
||||
'TG' => Yii::t('iso3166Codes', 'Togo'),
|
||||
'TK' => Yii::t('iso3166Codes', 'Tokelau'),
|
||||
'TO' => Yii::t('iso3166Codes', 'Tonga'),
|
||||
'TT' => Yii::t('iso3166Codes', 'Trinidad and Tobago'),
|
||||
'TN' => Yii::t('iso3166Codes', 'Tunisia'),
|
||||
'TR' => Yii::t('iso3166Codes', 'Turkey'),
|
||||
'TM' => Yii::t('iso3166Codes', 'Turkmenistan'),
|
||||
'TC' => Yii::t('iso3166Codes', 'Turks and Caicos Islands'),
|
||||
'TV' => Yii::t('iso3166Codes', 'Tuvalu'),
|
||||
'VI' => Yii::t('iso3166Codes', 'U.S. Virgin Islands'),
|
||||
'UG' => Yii::t('iso3166Codes', 'Uganda'),
|
||||
'UA' => Yii::t('iso3166Codes', 'Ukraine'),
|
||||
'AE' => Yii::t('iso3166Codes', 'United Arab Emirates'),
|
||||
'GB' => Yii::t('iso3166Codes', 'United Kingdom'),
|
||||
'US' => Yii::t('iso3166Codes', 'United States'),
|
||||
'UM' => Yii::t('iso3166Codes', 'United States Minor Outlying Islands'),
|
||||
'UY' => Yii::t('iso3166Codes', 'Uruguay'),
|
||||
'UZ' => Yii::t('iso3166Codes', 'Uzbekistan'),
|
||||
'VU' => Yii::t('iso3166Codes', 'Vanuatu'),
|
||||
'VA' => Yii::t('iso3166Codes', 'Vatican'),
|
||||
'VE' => Yii::t('iso3166Codes', 'Venezuela'),
|
||||
'VN' => Yii::t('iso3166Codes', 'Vietnam'),
|
||||
'WF' => Yii::t('iso3166Codes', 'Wallis and Futuna'),
|
||||
'EH' => Yii::t('iso3166Codes', 'Western Sahara'),
|
||||
'YE' => Yii::t('iso3166Codes', 'Yemen'),
|
||||
'ZM' => Yii::t('iso3166Codes', 'Zambia'),
|
||||
'ZW' => Yii::t('iso3166Codes', 'Zimbabwe')
|
||||
);
|
||||
static::$continentsTranslated = array(
|
||||
"AF" => Yii::t('iso3166Codes', 'Africa'),
|
||||
"AN" => Yii::t('iso3166Codes', 'Antarctica'),
|
||||
"AS" => Yii::t('iso3166Codes', 'Asia'),
|
||||
"EU" => Yii::t('iso3166Codes', 'Europa'),
|
||||
"NA" => Yii::t('iso3166Codes', 'North America'),
|
||||
"OC" => Yii::t('iso3166Codes', 'Oceania'),
|
||||
"SA" => Yii::t('iso3166Codes', 'South America')
|
||||
);
|
||||
}
|
||||
|
||||
public static function country($code, $translate = true)
|
||||
{
|
||||
return (isset(static::$countries[strtoupper($code)])) ? ($translate ? Yii::t('iso3166Codes', static::$countries[strtoupper($code)]) : static::$countries[strtoupper($code)]) : $code;
|
||||
return \Locale::getDisplayRegion("_$code", $translate ? Yii::$app->language : 'en');
|
||||
}
|
||||
|
||||
public static function phoneCode($code)
|
||||
@ -803,11 +523,6 @@ class iso3166Codes
|
||||
return (isset(static::$phoneCodes[strtoupper($code)])) ? static::$phoneCodes[strtoupper($code)] : 'N/A';
|
||||
}
|
||||
|
||||
public static function continent($code, $translate = true)
|
||||
{
|
||||
return (isset(static::$continents[strtoupper($code)])) ? ($translate ? Yii::t('iso3166Codes', static::$continents[strtoupper($code)]) : static::$continents[strtoupper($code)]) : Yii::t('iso3166Codes', 'Invalid Code');
|
||||
}
|
||||
|
||||
public static function isValid($code)
|
||||
{
|
||||
return isset(static::$countries[strtoupper($code)]);
|
||||
|
@ -1,342 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* HumHub
|
||||
* Copyright © 2014 The HumHub Project
|
||||
*
|
||||
* The texts of the GNU Affero General Public License with an additional
|
||||
* permission and of our proprietary license can be found at and
|
||||
* in the LICENSE file you have received along with this program.
|
||||
*
|
||||
* According to our dual licensing model, this program can be used either
|
||||
* under the terms of the GNU Affero General Public License, version 3,
|
||||
* or under a proprietary license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*/
|
||||
|
||||
namespace humhub\libs;
|
||||
|
||||
use humhub\models\Setting;
|
||||
|
||||
/**
|
||||
* ImageConverter provides a simple interface for converting or resizing images.
|
||||
*
|
||||
* @package humhub.modules_core.file.libs
|
||||
* @since 0.5
|
||||
*/
|
||||
class ImageConverter
|
||||
{
|
||||
|
||||
/**
|
||||
* Transforms given File to Jpeg
|
||||
*
|
||||
* @param String $sourceFile
|
||||
* @param String $targetFile
|
||||
* @param String $originalFileName (provide this when sourceFile has no extension e.g. tempfile)
|
||||
*/
|
||||
public static function TransformToJpeg($sourceFile, $targetFile)
|
||||
{
|
||||
|
||||
if (Setting::Get('imageMagickPath', 'file')) {
|
||||
$convertCommand = Setting::Get('imageMagickPath', 'file');
|
||||
$command = $convertCommand . " \"{$sourceFile}\" \"{$targetFile}\"";
|
||||
$ret = passthru($command);
|
||||
} else {
|
||||
$gdImage = self::getGDImageByFile($sourceFile);
|
||||
$gdImage = self::fixOrientation($gdImage, $sourceFile);
|
||||
imagejpeg($gdImage, $targetFile, 100);
|
||||
imagedestroy($gdImage);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resizes an given Image to an given Size
|
||||
*
|
||||
* Options Array:
|
||||
* width - in px
|
||||
* height - in px
|
||||
* mode:
|
||||
* force - creates image with given dimensions (default)
|
||||
* max - creates image with a maximum of given width / height
|
||||
*
|
||||
* @param String $sourceFile
|
||||
* @param String $targetFile
|
||||
* @param Array $options
|
||||
*/
|
||||
public static function Resize($sourceFile, $targetFile, $options = array())
|
||||
{
|
||||
|
||||
if (!isset($options['width']))
|
||||
$options['width'] = 0;
|
||||
|
||||
if (!isset($options['height']))
|
||||
$options['height'] = 0;
|
||||
|
||||
if (!isset($options['mode']))
|
||||
$options['mode'] = 'force';
|
||||
|
||||
if (Setting::Get('imageMagickPath', 'file')) {
|
||||
self::ResizeImageMagick($sourceFile, $targetFile, $options);
|
||||
} else {
|
||||
self::ResizeGD($sourceFile, $targetFile, $options);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize GD Libary Implementation
|
||||
*
|
||||
* @param type $sourceFile
|
||||
* @param type $targetFile
|
||||
* @param type $options
|
||||
*/
|
||||
private static function ResizeGD($sourceFile, $targetFile, $options = array())
|
||||
{
|
||||
|
||||
$width = $options['width'];
|
||||
$height = $options['height'];
|
||||
|
||||
$gdImage = self::getGDImageByFile($sourceFile);
|
||||
$gdImage = self::fixOrientation($gdImage, $sourceFile);
|
||||
|
||||
$sourceWidth = imagesx($gdImage);
|
||||
$sourceHeight = imagesy($gdImage);
|
||||
|
||||
$dst_x = 0;
|
||||
$dst_y = 0;
|
||||
$src_x = 0;
|
||||
$src_y = 0;
|
||||
$dst_w = $width;
|
||||
$dst_h = $height;
|
||||
$src_w = $sourceWidth;
|
||||
$src_h = $sourceHeight;
|
||||
|
||||
if ($options['mode'] == 'max') {
|
||||
|
||||
if ($sourceHeight > $height || $sourceWidth > $width) {
|
||||
|
||||
// http://snipplr.com/view/53183
|
||||
|
||||
if ($height == 0)
|
||||
$height = $sourceHeight;
|
||||
if ($width == 0)
|
||||
$width = $sourceWidth;
|
||||
|
||||
$w = $sourceWidth;
|
||||
$h = $sourceHeight;
|
||||
$max_w = $width;
|
||||
$max_h = $height;
|
||||
|
||||
// $w is the width of the current rectangle
|
||||
// $h is the height of the current rectangle
|
||||
// $max_w is the maximum width that an image can be sized
|
||||
// $max_h is the maximum height that an image can be sized
|
||||
// **** Here's where the magic is starts ****
|
||||
// Switch the concept of horiz/vertical/square to long/short side
|
||||
$short_side_len = ($w < $h ? $w : $h);
|
||||
$long_side_len = ($w > $h ? $w : $h);
|
||||
// Set a variable to the variable name of the output variable
|
||||
$ssvar = ($w > $h ? 'h' : 'w');
|
||||
$lsvar = ($w > $h ? 'w' : 'h');
|
||||
$maxLSvar = "max_" . $lsvar;
|
||||
$maxSSvar = "max_" . $ssvar;
|
||||
|
||||
// Do the first pass on the long side
|
||||
$ratio = $$maxLSvar / $long_side_len;
|
||||
$newSS = round($short_side_len * $ratio);
|
||||
$newLS = round($long_side_len * $ratio);
|
||||
|
||||
// *** Note - the only coditional block!
|
||||
// If short side is still out of limit, limit the short side and adjust
|
||||
if ($newSS > $$maxSSvar) {
|
||||
$ratio = $$maxSSvar / $newSS;
|
||||
$newLS = round($ratio * $newLS);
|
||||
$newSS = $$maxSSvar;
|
||||
}
|
||||
|
||||
// **** Here's where the magic ends ****
|
||||
// Re-couple the h/w (or w/h) with the long/shortside counterparts
|
||||
// $$ means it's a variable variable (dynamic assignment)
|
||||
$$ssvar = $newSS;
|
||||
$$lsvar = $newLS;
|
||||
|
||||
// Prep the return array
|
||||
#$dimensions['w'] = $w; // this is derived from either $ssvar or $lsvar
|
||||
#$dimensions['h'] = $h;
|
||||
|
||||
$width = $w;
|
||||
$height = $h;
|
||||
$dst_h = $h;
|
||||
$dst_w = $w;
|
||||
} else {
|
||||
$height = $sourceHeight;
|
||||
$width = $sourceWidth;
|
||||
$dst_h = $sourceHeight;
|
||||
$dst_w = $sourceWidth;
|
||||
}
|
||||
} else if ($options['mode'] == 'force') {
|
||||
|
||||
// When ratio not fit, crop it - requires given width & height
|
||||
if ($width != 0 && $height != 0) {
|
||||
if (($sourceWidth / $sourceHeight) != ($width / $height)) {
|
||||
|
||||
$_scale = min((float) ($sourceWidth / $width), (float) ($sourceHeight / $height));
|
||||
$cropX = (float) ($sourceWidth - ($_scale * $width));
|
||||
$cropY = (float) ($sourceHeight - ($_scale * $height));
|
||||
|
||||
// cropped image size
|
||||
$cropW = (float) ($sourceWidth - $cropX);
|
||||
$cropH = (float) ($sourceHeight - $cropY);
|
||||
|
||||
// crop the middle part of the image to fit proportions
|
||||
$crop = ImageCreateTrueColor($cropW, $cropH);
|
||||
ImageCopy(
|
||||
$crop, $gdImage, 0, 0, (int) ($cropX / 2), (int) ($cropY / 2), $cropW, $cropH
|
||||
);
|
||||
|
||||
$src_w = $cropW;
|
||||
$src_h = $cropH;
|
||||
|
||||
imagecopy($gdImage, $crop, 0, 0, 0, 0, $src_w, $src_h);
|
||||
}
|
||||
} elseif ($width == 0) {
|
||||
$width = $sourceWidth;
|
||||
} elseif ($height == 0) {
|
||||
$height = $sourceHeight;
|
||||
} else {
|
||||
$width = $sourceWidth;
|
||||
$height = $sourceHeight;
|
||||
}
|
||||
}
|
||||
|
||||
// Create new Image
|
||||
$newGdImage = imagecreatetruecolor($width, $height);
|
||||
|
||||
if (isset($options['transparent']) && $options['transparent']) {
|
||||
imagealphablending($newGdImage, false);
|
||||
imagesavealpha($newGdImage, true);
|
||||
$transparent = imagecolorallocatealpha($newGdImage, 255, 255, 255, 127);
|
||||
imagefilledrectangle($newGdImage, 0, 0, $width, $height, $transparent);
|
||||
}
|
||||
|
||||
imagecopyresampled($newGdImage, $gdImage, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
|
||||
|
||||
list($hw, $hx, $imageType) = getimagesize($sourceFile);
|
||||
|
||||
switch ($imageType) {
|
||||
case IMAGETYPE_PNG:
|
||||
imagepng($newGdImage, $targetFile);
|
||||
break;
|
||||
case IMAGETYPE_GIF:
|
||||
imagegif($newGdImage, $targetFile);
|
||||
break;
|
||||
case IMAGETYPE_JPEG:
|
||||
imagejpeg($newGdImage, $targetFile, 100);
|
||||
break;
|
||||
}
|
||||
imagedestroy($gdImage);
|
||||
imagedestroy($newGdImage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize Image Magick Implementation
|
||||
*
|
||||
* @param type $sourceFile
|
||||
* @param type $targetFile
|
||||
* @param type $options
|
||||
*/
|
||||
private static function ResizeImageMagick($sourceFile, $targetFile, $options = array())
|
||||
{
|
||||
$convertCommand = Setting::Get('imageMagickPath', 'file');
|
||||
$width = (int) $options['width'];
|
||||
$height = (int) $options['height'];
|
||||
|
||||
if ($options['mode'] == 'max') {
|
||||
|
||||
if ($width && $height)
|
||||
$command = $convertCommand . " -quality 100 -density 300 \"{$sourceFile}\" -resize '{$width}x{$height}>' \"{$targetFile}\"";
|
||||
elseif ($width)
|
||||
$command = $convertCommand . " -quality 100 -density 300 \"{$sourceFile}\" -resize '{$width}x>' \"{$targetFile}\"";
|
||||
elseif ($height)
|
||||
$command = $convertCommand . " -quality 100 -density 300 \"{$sourceFile}\" -resize 'x{$height}>' \"{$targetFile}\"";
|
||||
|
||||
$ret = passthru($command);
|
||||
} elseif ($options['mode'] == 'force') {
|
||||
$command = $convertCommand . " \"{$sourceFile}\" -gravity center -quality 100 -resize {$width}x{$height}^ -extent {$width}x{$height} \"{$targetFile}\"";
|
||||
$ret = passthru($command);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates GD Image Resource by given Filename
|
||||
*
|
||||
* @param String $fileName
|
||||
* @return resource GD Image
|
||||
*/
|
||||
public static function getGDImageByFile($fileName)
|
||||
{
|
||||
|
||||
list($width, $height, $imageType) = getimagesize($fileName);
|
||||
|
||||
switch ($imageType) {
|
||||
case IMAGETYPE_PNG:
|
||||
$gdImage = imagecreatefrompng($fileName);
|
||||
break;
|
||||
case IMAGETYPE_GIF:
|
||||
$gdImage = imagecreatefromgif($fileName);
|
||||
break;
|
||||
case IMAGETYPE_JPEG:
|
||||
$gdImage = imagecreatefromjpeg($fileName);
|
||||
break;
|
||||
}
|
||||
|
||||
return $gdImage;
|
||||
}
|
||||
|
||||
public static function fixOrientation($image, $filename)
|
||||
{
|
||||
$exif = @exif_read_data($filename);
|
||||
if (is_array($exif) && !empty($exif['Orientation'])) {
|
||||
switch ($exif['Orientation']) {
|
||||
case 8:
|
||||
$image = imagerotate($image, 90, 0);
|
||||
break;
|
||||
case 3:
|
||||
$image = imagerotate($image, 180, 0);
|
||||
break;
|
||||
case 6:
|
||||
$image = imagerotate($image, -90, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $image;
|
||||
}
|
||||
|
||||
public static function checkTransparent($im)
|
||||
{
|
||||
|
||||
$im = self::getGDImageByFile($im);
|
||||
|
||||
$width = imagesx($im); // Get the width of the image
|
||||
$height = imagesy($im); // Get the height of the image
|
||||
// We run the image pixel by pixel and as soon as we find a transparent pixel we stop and return true.
|
||||
for ($i = 0; $i < $width; $i++) {
|
||||
for ($j = 0; $j < $height; $j++) {
|
||||
$rgba = imagecolorat($im, $i, $j);
|
||||
if (($rgba & 0x7F000000) >> 24) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we dont find any pixel the function will return false.
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -1,11 +1,21 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\libs;
|
||||
|
||||
use Yii;
|
||||
use yii\web\UploadedFile;
|
||||
use yii\helpers\Url;
|
||||
use humhub\modules\file\libs\ImageConverter;
|
||||
|
||||
/**
|
||||
* LogoImage
|
||||
*/
|
||||
class LogoImage
|
||||
{
|
||||
|
||||
@ -19,11 +29,6 @@ class LogoImage
|
||||
*/
|
||||
protected $folder_images = "logo_image";
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the URl of Logo Image
|
||||
*
|
||||
|
@ -1,26 +1,14 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* HumHub
|
||||
* Copyright © 2014 The HumHub Project
|
||||
*
|
||||
* The texts of the GNU Affero General Public License with an additional
|
||||
* permission and of our proprietary license can be found at and
|
||||
* in the LICENSE file you have received along with this program.
|
||||
*
|
||||
* According to our dual licensing model, this program can be used either
|
||||
* under the terms of the GNU Affero General Public License, version 3,
|
||||
* or under a proprietary license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\libs;
|
||||
|
||||
use humhub\libs\ImageConverter;
|
||||
use humhub\modules\file\libs\ImageConverter;
|
||||
|
||||
/**
|
||||
* ProfileBannerImage is responsible for the profile banner images.
|
||||
@ -32,7 +20,6 @@ use humhub\libs\ImageConverter;
|
||||
* "" = Resized profile image
|
||||
* "_org" = Orginal uploaded file
|
||||
*
|
||||
* @package humhub.modules_core.file
|
||||
* @since 0.5
|
||||
* @author Luke
|
||||
*/
|
||||
|
@ -1,28 +1,16 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* HumHub
|
||||
* Copyright © 2014 The HumHub Project
|
||||
*
|
||||
* The texts of the GNU Affero General Public License with an additional
|
||||
* permission and of our proprietary license can be found at and
|
||||
* in the LICENSE file you have received along with this program.
|
||||
*
|
||||
* According to our dual licensing model, this program can be used either
|
||||
* under the terms of the GNU Affero General Public License, version 3,
|
||||
* or under a proprietary license.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\libs;
|
||||
|
||||
use Yii;
|
||||
use yii\helpers\Url;
|
||||
use humhub\libs\ImageConverter;
|
||||
use humhub\modules\file\libs\ImageConverter;
|
||||
|
||||
/**
|
||||
* ProfileImage is responsible for all profile images.
|
||||
@ -34,7 +22,6 @@ use humhub\libs\ImageConverter;
|
||||
* "" = Resized profile image
|
||||
* "_org" = Orginal uploaded file
|
||||
*
|
||||
* @package humhub.modules_core.file
|
||||
* @since 0.5
|
||||
* @author Luke
|
||||
*/
|
||||
|
@ -85,7 +85,7 @@ class SelfTest
|
||||
|
||||
$icuVersion = (defined('INTL_ICU_VERSION')) ? INTL_ICU_VERSION : 0;
|
||||
$icuMinVersion = '4.8.1';
|
||||
$title = 'PHP - INTL Extension - ICU Version (' . INTL_ICU_VERSION . ')';
|
||||
$title = 'PHP - INTL Extension - ICU Version (' . $icuVersion . ')';
|
||||
if (version_compare($icuVersion, $icuMinVersion, '>=')) {
|
||||
$checks[] = array(
|
||||
'title' => Yii::t('base', $title),
|
||||
@ -100,7 +100,7 @@ class SelfTest
|
||||
}
|
||||
$icuDataVersion = (defined('INTL_ICU_DATA_VERSION')) ? INTL_ICU_DATA_VERSION : 0;
|
||||
$icuMinDataVersion = '4.8.1';
|
||||
$title = 'PHP - INTL Extension - ICU Data Version (' . INTL_ICU_DATA_VERSION . ')';
|
||||
$title = 'PHP - INTL Extension - ICU Data Version (' . $icuDataVersion . ')';
|
||||
if (version_compare($icuDataVersion, $icuMinDataVersion, '>=')) {
|
||||
$checks[] = array(
|
||||
'title' => Yii::t('base', $title),
|
||||
|
132
protected/humhub/libs/ThemeHelper.php
Normal file
132
protected/humhub/libs/ThemeHelper.php
Normal file
@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\libs;
|
||||
|
||||
use Yii;
|
||||
use humhub\components\Theme;
|
||||
use yii\helpers\ArrayHelper;
|
||||
|
||||
/**
|
||||
* ThemeHelper
|
||||
*
|
||||
* @since 1.1
|
||||
* @author Luke
|
||||
*/
|
||||
class ThemeHelper
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns an array of all available themes.
|
||||
*
|
||||
* @return Array Theme instances
|
||||
*/
|
||||
public static function getThemes()
|
||||
{
|
||||
$themes = self::getThemesByPath(Yii::getAlias('@webroot/themes'));
|
||||
|
||||
// Collect themes provided by modules
|
||||
foreach (Yii::$app->getModules() as $id => $module) {
|
||||
if (is_array($module)) {
|
||||
$module = Yii::$app->getModule($id);
|
||||
}
|
||||
|
||||
$moduleThemePath = $module->getBasePath() . DIRECTORY_SEPARATOR . 'themes';
|
||||
if (is_dir($moduleThemePath)) {
|
||||
$themes = ArrayHelper::merge($themes, self::getThemesByPath($moduleThemePath, ['publishResources' => true]));
|
||||
}
|
||||
}
|
||||
|
||||
return $themes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an array of Theme instances of a given directory
|
||||
*
|
||||
* @param string $path the theme directory
|
||||
* @param type $additionalOptions options for Theme instance
|
||||
* @return Theme[]
|
||||
*/
|
||||
public static function getThemesByPath($path, $additionalOptions = [])
|
||||
{
|
||||
$themes = [];
|
||||
if (is_dir($path)) {
|
||||
foreach (scandir($path) as $file) {
|
||||
|
||||
// Skip dots and non directories
|
||||
if ($file == "." || $file == ".." || !is_dir($path . DIRECTORY_SEPARATOR . $file)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$themes[] = Yii::createObject(ArrayHelper::merge([
|
||||
'class' => 'humhub\components\Theme',
|
||||
'basePath' => $path . DIRECTORY_SEPARATOR . $file,
|
||||
'name' => $file
|
||||
], $additionalOptions));
|
||||
}
|
||||
}
|
||||
return $themes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a Theme by given name
|
||||
*
|
||||
* @param string $name of the theme
|
||||
* @return Theme
|
||||
*/
|
||||
public static function getThemeByName($name)
|
||||
{
|
||||
foreach (self::getThemes() as $theme) {
|
||||
if ($theme->name === $name) {
|
||||
return $theme;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns configuration array of given theme
|
||||
*
|
||||
* @param Theme|string $theme name or theme instance
|
||||
* @return array Configuration
|
||||
*/
|
||||
public static function getThemeConfig($theme)
|
||||
{
|
||||
if (is_string($theme)) {
|
||||
$theme = self::getThemeByName($theme);
|
||||
}
|
||||
|
||||
if ($theme === null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$theme->beforeActivate();
|
||||
|
||||
return [
|
||||
'components' => [
|
||||
'view' => [
|
||||
'theme' => [
|
||||
'name' => $theme->name,
|
||||
'basePath' => $theme->getBasePath(),
|
||||
'publishResources' => $theme->publishResources,
|
||||
],
|
||||
],
|
||||
'mailer' => [
|
||||
'view' => [
|
||||
'theme' => [
|
||||
'name' => $theme->name,
|
||||
'basePath' => $theme->getBasePath(),
|
||||
'publishResources' => $theme->publishResources,
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
}
|
158
protected/humhub/libs/Viewable.php
Normal file
158
protected/humhub/libs/Viewable.php
Normal file
@ -0,0 +1,158 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\libs;
|
||||
|
||||
use Yii;
|
||||
use yii\base\Component;
|
||||
use yii\base\ViewContextInterface;
|
||||
|
||||
/**
|
||||
* Viewable provides view rendering support including layout and different
|
||||
* output formats (e.g. text, web or mail=.
|
||||
*
|
||||
* @since 1.1
|
||||
* @author Luke
|
||||
*/
|
||||
abstract class Viewable extends Component implements ViewContextInterface
|
||||
{
|
||||
|
||||
const OUTPUT_WEB = 'web';
|
||||
const OUTPUT_MAIL = 'mail';
|
||||
const OUTPUT_MAIL_PLAINTEXT = 'mail_plaintext';
|
||||
const OUTPUT_TEXT = 'text';
|
||||
|
||||
/**
|
||||
* Name of the view, used for rendering the event
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $viewName = null;
|
||||
|
||||
/**
|
||||
* View path
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
public $viewPath = null;
|
||||
|
||||
/**
|
||||
* Layout file for web version
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $layoutWeb;
|
||||
|
||||
/**
|
||||
* Layout file for mail version
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $layoutMail;
|
||||
|
||||
/**
|
||||
* Layout file for mail plaintext version
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $layoutMailPlaintext;
|
||||
|
||||
/**
|
||||
* Assambles all parameter required for rendering the view.
|
||||
*
|
||||
* @return array all view parameter
|
||||
*/
|
||||
protected function getViewParams($params = [])
|
||||
{
|
||||
$params['originator'] = $this->originator;
|
||||
$params['source'] = $this->source;
|
||||
$params['contentContainer'] = $this->container;
|
||||
$params['record'] = $this->record;
|
||||
$params['url'] = $this->getUrl();
|
||||
|
||||
return $params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the notification
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function render($mode = self::OUTPUT_WEB, $params = [])
|
||||
{
|
||||
$viewFile = $this->getViewFile($mode);
|
||||
$viewParams = $this->getViewParams($params);
|
||||
|
||||
$result = Yii::$app->getView()->renderFile($viewFile, $viewParams, $this);
|
||||
|
||||
if ($mode == self::OUTPUT_TEXT) {
|
||||
return strip_tags($result);
|
||||
}
|
||||
|
||||
$viewParams['content'] = $result;
|
||||
return Yii::$app->getView()->renderFile($this->getLayoutFile($mode), $viewParams, $this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the correct view file
|
||||
*
|
||||
* @param string $mode the output mode
|
||||
* @return string the view file
|
||||
*/
|
||||
protected function getViewFile($mode)
|
||||
{
|
||||
$viewFile = $this->getViewPath() . '/' . $this->viewName . '.php';
|
||||
$alternativeViewFile = "";
|
||||
|
||||
// Lookup alternative view file based on view mode
|
||||
if ($mode == self::OUTPUT_MAIL) {
|
||||
$alternativeViewFile = $this->getViewPath() . '/mail/' . $this->viewName . '.php';
|
||||
} elseif ($mode === self::OUTPUT_MAIL_PLAINTEXT) {
|
||||
$alternativeViewFile = $this->getViewPath() . '/mail/plaintext/' . $this->viewName . '.php';
|
||||
}
|
||||
|
||||
if ($alternativeViewFile != "" && file_exists($alternativeViewFile)) {
|
||||
$viewFile = $alternativeViewFile;
|
||||
}
|
||||
|
||||
return $viewFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the layout file
|
||||
*
|
||||
* @param string $mode the output mode
|
||||
* @return string the layout file
|
||||
*/
|
||||
protected function getLayoutFile($mode)
|
||||
{
|
||||
if ($mode == self::OUTPUT_MAIL_PLAINTEXT) {
|
||||
return $this->layoutMailPlaintext;
|
||||
} elseif ($mode == self::OUTPUT_MAIL) {
|
||||
return $this->layoutMail;
|
||||
}
|
||||
|
||||
return $this->layoutWeb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the directory containing the view files for this event.
|
||||
* The default implementation returns the 'views' subdirectory under the directory containing the notification class file.
|
||||
* @return string the directory containing the view files for this notification.
|
||||
*/
|
||||
public function getViewPath()
|
||||
{
|
||||
if ($this->viewPath !== null) {
|
||||
return Yii::getAlias($this->viewPath);
|
||||
}
|
||||
|
||||
$class = new \ReflectionClass($this);
|
||||
return dirname($class->getFileName()) . DIRECTORY_SEPARATOR . 'views';
|
||||
}
|
||||
|
||||
}
|
@ -1,56 +1,37 @@
|
||||
<?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 [
|
||||
'Allow' => '',
|
||||
'Back' => '',
|
||||
'Choose language:' => '',
|
||||
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '',
|
||||
'Could not determine content container!' => '',
|
||||
'Could not find content of addon!' => '',
|
||||
'Default' => '',
|
||||
'Deny' => '',
|
||||
'Language' => '',
|
||||
'Login' => '',
|
||||
'Module is not on this content container enabled!' => '',
|
||||
'Next' => '',
|
||||
'Please type at least 3 characters' => '',
|
||||
'Save' => '',
|
||||
'<strong>Latest</strong> updates' => '<strong>Zagueras</strong> actividatz',
|
||||
'Account settings' => 'Achustes d\'a cuenta',
|
||||
'Administration' => 'Administración',
|
||||
'Back to dashboard' => 'Tornar a Encieto',
|
||||
'Collapse' => 'Zarrar',
|
||||
'Error' => 'Error',
|
||||
'Expand' => 'Esbandir',
|
||||
'Insufficent permissions to create content!' => 'Premisos insuficients ta creyar una cuenta!',
|
||||
'It looks like you may have taken the wrong turn.' => 'Pareixe que has tomau o camín incorrecto.',
|
||||
'Latest news' => 'Zagueras noticias',
|
||||
'Logout' => 'Zarrar sesión',
|
||||
'Menu' => 'Menú',
|
||||
'My profile' => 'O mío perfil',
|
||||
'New profile image' => 'Nueva imachen de perfil',
|
||||
'Oooops...' => 'Oooops...',
|
||||
'Search' => 'Buscar',
|
||||
'Search for users and spaces' => 'Buscar usuarios y espacios',
|
||||
'Space not found!' => 'Espacio no trobau!',
|
||||
'User Approvals' => 'Aprobacions d\'usuario',
|
||||
'User not found!' => 'Usuario no trobau!',
|
||||
'You cannot create public visible content!' => 'No puetz creyar conteniu publico visible!',
|
||||
'Your daily summary' => 'Resumen diario',
|
||||
];
|
||||
return array (
|
||||
'<strong>Latest</strong> updates' => '<strong>Zagueras</strong> actividatz',
|
||||
'Account settings' => 'Achustes d\'a cuenta',
|
||||
'Administration' => 'Administración',
|
||||
'Allow' => '',
|
||||
'Back' => '',
|
||||
'Back to dashboard' => 'Tornar a Encieto',
|
||||
'Choose language:' => '',
|
||||
'Collapse' => 'Zarrar',
|
||||
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '',
|
||||
'Could not determine content container!' => '',
|
||||
'Could not find content of addon!' => '',
|
||||
'Default' => '',
|
||||
'Deny' => '',
|
||||
'Error' => 'Error',
|
||||
'Expand' => 'Esbandir',
|
||||
'It looks like you may have taken the wrong turn.' => 'Pareixe que has tomau o camín incorrecto.',
|
||||
'Language' => '',
|
||||
'Latest news' => 'Zagueras noticias',
|
||||
'Login' => '',
|
||||
'Logout' => 'Zarrar sesión',
|
||||
'Menu' => 'Menú',
|
||||
'Module is not on this content container enabled!' => '',
|
||||
'My profile' => 'O mío perfil',
|
||||
'New profile image' => 'Nueva imachen de perfil',
|
||||
'Next' => '',
|
||||
'Ok' => '',
|
||||
'Oooops...' => 'Oooops...',
|
||||
'Please type at least 3 characters' => '',
|
||||
'Save' => 'Uložit',
|
||||
'Search' => 'Buscar',
|
||||
'Search for users and spaces' => 'Buscar usuarios y espacios',
|
||||
'Space not found!' => 'Espacio no trobau!',
|
||||
'User not found!' => 'Usuario no trobau!',
|
||||
'Your daily summary' => 'Resumen diario',
|
||||
);
|
||||
|
@ -1,21 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Message translations.
|
||||
*
|
||||
* This file is automatically generated by 'yiic 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 array (
|
||||
'Global {global} array cleaned using {method} method.' => '',
|
||||
);
|
File diff suppressed because one or more lines are too long
@ -1,56 +1,37 @@
|
||||
<?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 [
|
||||
'Allow' => '',
|
||||
'Default' => '',
|
||||
'Deny' => '',
|
||||
'Next' => '',
|
||||
'Please type at least 3 characters' => '',
|
||||
'Save' => '',
|
||||
'<strong>Latest</strong> updates' => '<strong>آخر</strong> التحديثات',
|
||||
'Account settings' => 'إعدادات الحساب',
|
||||
'Administration' => 'الإدارة',
|
||||
'Back' => 'عودة',
|
||||
'Back to dashboard' => 'عودة لسطح المكتب',
|
||||
'Choose language:' => 'خيارات اللغه:',
|
||||
'Collapse' => 'إغلاق',
|
||||
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '@Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!@',
|
||||
'Could not determine content container!' => 'لم يمكن تحديد content container!',
|
||||
'Could not find content of addon!' => 'لم يمكن ايجاد محتويات الإضافة',
|
||||
'Error' => 'خطأ',
|
||||
'Expand' => 'توسعة',
|
||||
'Insufficent permissions to create content!' => 'لا توجد الصلاحية لكتابة محتويات',
|
||||
'It looks like you may have taken the wrong turn.' => 'يبدو انك أتيت للصفحة الخطأ',
|
||||
'Language' => 'اللغة',
|
||||
'Latest news' => 'آخر الأخبار',
|
||||
'Login' => 'تسجيل الدخول',
|
||||
'Logout' => 'تسجيل الخروج',
|
||||
'Menu' => 'القائمة',
|
||||
'Module is not on this content container enabled!' => 'الموديل ليس متاحاً في هذه الخانة',
|
||||
'My profile' => 'صفحتي الشخصية',
|
||||
'New profile image' => 'صورة شخصية جديدة',
|
||||
'Oooops...' => 'يالهوي...',
|
||||
'Search' => 'بحث',
|
||||
'Search for users and spaces' => 'البحث عن مستخدمين و باحات',
|
||||
'Space not found!' => 'لم اتمكن من إيجاد الباحة!',
|
||||
'User Approvals' => 'موافقات الأعضاء',
|
||||
'User not found!' => 'لم يتم إيجاد العضو',
|
||||
'You cannot create public visible content!' => 'ليس مسموحاً لك كتابة مواضيع للنشر العام!',
|
||||
'Your daily summary' => 'المختصر اليومي',
|
||||
];
|
||||
return array (
|
||||
'<strong>Latest</strong> updates' => '<strong>آخر</strong> التحديثات',
|
||||
'Account settings' => 'إعدادات الحساب',
|
||||
'Administration' => 'الإدارة',
|
||||
'Allow' => '',
|
||||
'Back' => 'عودة',
|
||||
'Back to dashboard' => 'عودة لسطح المكتب',
|
||||
'Choose language:' => 'خيارات اللغه:',
|
||||
'Collapse' => 'إغلاق',
|
||||
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '@Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!@',
|
||||
'Could not determine content container!' => 'لم يمكن تحديد content container!',
|
||||
'Could not find content of addon!' => 'لم يمكن ايجاد محتويات الإضافة',
|
||||
'Default' => '',
|
||||
'Deny' => '',
|
||||
'Error' => 'خطأ',
|
||||
'Expand' => 'توسعة',
|
||||
'It looks like you may have taken the wrong turn.' => 'يبدو انك أتيت للصفحة الخطأ',
|
||||
'Language' => 'اللغة',
|
||||
'Latest news' => 'آخر الأخبار',
|
||||
'Login' => 'تسجيل الدخول',
|
||||
'Logout' => 'تسجيل الخروج',
|
||||
'Menu' => 'القائمة',
|
||||
'Module is not on this content container enabled!' => 'الموديل ليس متاحاً في هذه الخانة',
|
||||
'My profile' => 'صفحتي الشخصية',
|
||||
'New profile image' => 'صورة شخصية جديدة',
|
||||
'Next' => '',
|
||||
'Ok' => '',
|
||||
'Oooops...' => 'يالهوي...',
|
||||
'Please type at least 3 characters' => '',
|
||||
'Save' => 'حفظ',
|
||||
'Search' => 'بحث',
|
||||
'Search for users and spaces' => 'البحث عن مستخدمين و باحات',
|
||||
'Space not found!' => 'لم اتمكن من إيجاد الباحة!',
|
||||
'User not found!' => 'لم يتم إيجاد العضو',
|
||||
'Your daily summary' => 'المختصر اليومي',
|
||||
);
|
||||
|
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
return array (
|
||||
'Global {global} array cleaned using {method} method.' => '@Global {global} array cleaned using {method} method.@',
|
||||
);
|
@ -1 +1 @@
|
||||
{"Invalid request.":["Грешна заявка."],"Results":["Резултати"],"Show more results":["Покажи още резултати"],"Sorry, nothing found!":["Нищо не е намерено!"],"Welcome to %appName%":["Добре дошли в %appName%"],"<strong>Latest</strong> updates":["<strong>Последни</strong> ъпдейти"],"Account settings":["Настройки на акаунта"],"Administration":["Администрация"],"Back":["Назад"],"Back to dashboard":["Върни се в работното място"],"Choose language:":["Избери език:"],"Collapse":["Свий"],"Error":["Грешка"],"Expand":["Разшири"],"Language":["Език"],"Latest news":["Последни новини"],"Login":["Вход"],"Logout":["Изход"],"Menu":["Меню"],"My profile":["Моят Профил"],"New profile image":["Нова профилна картинка"],"Oooops...":["Опаля..."],"Search":["Търси"],"Search for users and spaces":["Търси хора и зони"],"Space not found!":["Зоната не е открита!"],"User not found!":["Потребителя не е намерен!","Потребителят не е намерен!"],"Access denied!":["Достъп отказан!"],"Visible for all":["Видима за всички"]," Invite and request":["Покани и заявки"],"Everyone can enter":["Всеки може да се присъедини"],"Invite and request":["Покани и заявки"],"Only by invite":["Само при покана"],"Private (Invisible)":["Лична зона (Невидима)"],"End guide":["Край на урока"],"Next »":["Напред »"],"« Prev":["« Назад"],"<strong>Hurray!</strong> That's all for now.":["<strong>¡Bien!</strong> Eso es todo por ahora."],"<strong>Dashboard</strong>":["<strong>Inicio</strong>"],"This is your dashboard.<br><br>Any new activities or posts that might interest you will be displayed here.":["Este es tu inicio.<br><br>Todas las nuevas actividades serán mostradas aquí."],"<strong>Edit</strong> account":["<strong>Editar</strong> cuenta"],"<strong>Hurray!</strong> The End.":["<strong>¡Bien!</strong> Has acabado."],"<strong>Hurray!</strong> You're done!":["<strong>¡Bien!</strong> ya está!"],"<strong>Profile</strong> menu":["Menú de <strong>perfil</strong>"],"<strong>Profile</strong> photo":["Fotos de <strong>perfil</strong>"],"<strong>Profile</strong> stream":["Actividad del <strong>perfil</strong> "],"<strong>User profile</strong>":["<strong>Perfil de usuario</strong>"],"Click on this button to update your profile and account settings. You can also add more information to your profile.":["Haz click en este botón para actualizar tu perfil y los ajustes de cuenta. También puedes añadir más información a tu perfil."],"Each profile has its own pin board. Your posts will also appear on the dashboards of those users who are following you.":["Cada perfil tiene su muro. Tus entradas también aparecerán en el Inicio de los usuarios que te sigan."],"Just like in the space, the user profile can be personalized with various modules.<br><br>You can see which modules are available for your profile by looking them in “Modules” in the account settings menu.":["Como en un espacio, los perfiles de usuarios pueden ser personalizados con varios módulos. <br><br>Puedes ver qué módulos están disponibles para tu perfil buscándolos en \"Módulos\" en el menú Ajustes de cuenta."],"This is your public user profile, which can be seen by any registered user.":["Este es tu perfil de usuario público, que será visible por cualquier usuario registrado."],"Upload a new profile photo by simply clicking here or by drag&drop. Do just the same for updating your cover photo.":["Sube una nueva foto haciendo click aquí o simplemente arrástrala. Haz lo mismo para actualizar tu imagen de cabecera."],"You've completed the user profile guide!":["¡Has completado la guía de los perfiles de usuario!"],"This user account is not approved yet!":["Потребителският профил не е потвърден!"],"You need to login to view this user profile!":["Трябва да си логнат за да гледаш този профил!"],"Back to modules":["Върни се при модулите"],"Cancel":["Отказ"],"Delete":["Изтрий"],"Delete category":["Изтрий категория"],"Delete link":["Изтрий линк"],"Link":["Линк"],"Linklist":["Линк списак"],"Save":["Запази"],"Messages":["Съобщения"],"No users.":["Няма потребители"],"Get a list":["Вземи списак"],"Notes":["Бележки"],"Polls":["Анкети"],"by :displayName":["от :displayName"],"Tasks":["Задачи"],"Translation Manager":["Мениджър за преводи"],"Translations":["Преводи"]}
|
||||
{"Invalid request.":["Грешна заявка."],"Results":["Резултати"],"Show more results":["Покажи още резултати"],"Sorry, nothing found!":["Нищо не е намерено!"],"Welcome to %appName%":["Добре дошли в %appName%"],"<strong>Latest</strong> updates":["<strong>Последни</strong> ъпдейти"],"Account settings":["Настройки на акаунта"],"Administration":["Администрация"],"Back":["Назад"],"Back to dashboard":["Върни се в работното място"],"Choose language:":["Избери език:"],"Collapse":["Свий"],"Error":["Грешка"],"Expand":["Разшири"],"Language":["Език"],"Latest news":["Последни новини"],"Login":["Вход"],"Logout":["Изход"],"Menu":["Меню"],"My profile":["Моят Профил"],"New profile image":["Нова профилна картинка"],"Oooops...":["Опаля..."],"Search":["Търси"],"Search for users and spaces":["Търси хора и зони"],"Space not found!":["Зоната не е открита!"],"User not found!":["Потребителят не е намерен!"],"Access denied!":["Достъп отказан!"],"Visible for all":["Видима за всички"]," Invite and request":["Покани и заявки"],"Everyone can enter":["Всеки може да се присъедини"],"Invite and request":["Покани и заявки"],"Only by invite":["Само при покана"],"Private (Invisible)":["Лична зона (Невидима)"],"End guide":["Край на урока"],"Next »":["Напред »"],"« Prev":["« Назад"],"<strong>Hurray!</strong> That's all for now.":["<strong>¡Bien!</strong> Eso es todo por ahora."],"<strong>Dashboard</strong>":["<strong>Inicio</strong>"],"This is your dashboard.<br><br>Any new activities or posts that might interest you will be displayed here.":["Este es tu inicio.<br><br>Todas las nuevas actividades serán mostradas aquí."],"<strong>Edit</strong> account":["<strong>Editar</strong> cuenta"],"<strong>Hurray!</strong> The End.":["<strong>¡Bien!</strong> Has acabado."],"<strong>Hurray!</strong> You're done!":["<strong>¡Bien!</strong> ya está!"],"<strong>Profile</strong> menu":["Menú de <strong>perfil</strong>"],"<strong>Profile</strong> photo":["Fotos de <strong>perfil</strong>"],"<strong>Profile</strong> stream":["Actividad del <strong>perfil</strong> "],"<strong>User profile</strong>":["<strong>Perfil de usuario</strong>"],"Click on this button to update your profile and account settings. You can also add more information to your profile.":["Haz click en este botón para actualizar tu perfil y los ajustes de cuenta. También puedes añadir más información a tu perfil."],"Each profile has its own pin board. Your posts will also appear on the dashboards of those users who are following you.":["Cada perfil tiene su muro. Tus entradas también aparecerán en el Inicio de los usuarios que te sigan."],"Just like in the space, the user profile can be personalized with various modules.<br><br>You can see which modules are available for your profile by looking them in “Modules” in the account settings menu.":["Como en un espacio, los perfiles de usuarios pueden ser personalizados con varios módulos. <br><br>Puedes ver qué módulos están disponibles para tu perfil buscándolos en \"Módulos\" en el menú Ajustes de cuenta."],"This is your public user profile, which can be seen by any registered user.":["Este es tu perfil de usuario público, que será visible por cualquier usuario registrado."],"Upload a new profile photo by simply clicking here or by drag&drop. Do just the same for updating your cover photo.":["Sube una nueva foto haciendo click aquí o simplemente arrástrala. Haz lo mismo para actualizar tu imagen de cabecera."],"You've completed the user profile guide!":["¡Has completado la guía de los perfiles de usuario!"],"This user account is not approved yet!":["Потребителският профил не е потвърден!"],"You need to login to view this user profile!":["Трябва да си логнат за да гледаш този профил!"],"Back to modules":["Върни се при модулите"],"Cancel":["Отказ"],"Delete":["Изтрий"],"Delete category":["Изтрий категория"],"Delete link":["Изтрий линк"],"Link":["Линк"],"Linklist":["Линк списак"],"Save":["Запази"],"Messages":["Съобщения"],"No users.":["Няма потребители"],"Get a list":["Вземи списак"],"Notes":["Бележки"],"Polls":["Анкети"],"by :displayName":["от :displayName"],"Tasks":["Задачи"],"Translation Manager":["Мениджър за преводи"],"Translations":["Преводи"]}
|
@ -1,56 +1,37 @@
|
||||
<?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 [
|
||||
'Allow' => '',
|
||||
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '',
|
||||
'Could not determine content container!' => '',
|
||||
'Could not find content of addon!' => '',
|
||||
'Default' => '',
|
||||
'Deny' => '',
|
||||
'Insufficent permissions to create content!' => '',
|
||||
'It looks like you may have taken the wrong turn.' => '',
|
||||
'Module is not on this content container enabled!' => '',
|
||||
'Next' => '',
|
||||
'Please type at least 3 characters' => '',
|
||||
'Save' => '',
|
||||
'User Approvals' => '',
|
||||
'You cannot create public visible content!' => '',
|
||||
'Your daily summary' => '',
|
||||
'<strong>Latest</strong> updates' => '<strong>Последни</strong> ъпдейти',
|
||||
'Account settings' => 'Настройки на акаунта',
|
||||
'Administration' => 'Администрация',
|
||||
'Back' => 'Назад',
|
||||
'Back to dashboard' => 'Върни се в работното място',
|
||||
'Choose language:' => 'Избери език:',
|
||||
'Collapse' => 'Свий',
|
||||
'Error' => 'Грешка',
|
||||
'Expand' => 'Разшири',
|
||||
'Language' => 'Език',
|
||||
'Latest news' => 'Последни новини',
|
||||
'Login' => 'Вход',
|
||||
'Logout' => 'Изход',
|
||||
'Menu' => 'Меню',
|
||||
'My profile' => 'Моят Профил',
|
||||
'New profile image' => 'Нова профилна картинка',
|
||||
'Oooops...' => 'Опаля...',
|
||||
'Search' => 'Търси',
|
||||
'Search for users and spaces' => 'Търси хора и зони',
|
||||
'Space not found!' => 'Зоната не е открита!',
|
||||
'User not found!' => 'Потребителя не е намерен!',
|
||||
];
|
||||
return array (
|
||||
'<strong>Latest</strong> updates' => '<strong>Последни</strong> ъпдейти',
|
||||
'Account settings' => 'Настройки на акаунта',
|
||||
'Administration' => 'Администрация',
|
||||
'Allow' => '',
|
||||
'Back' => 'Назад',
|
||||
'Back to dashboard' => 'Върни се в работното място',
|
||||
'Choose language:' => 'Избери език:',
|
||||
'Collapse' => 'Свий',
|
||||
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '',
|
||||
'Could not determine content container!' => '',
|
||||
'Could not find content of addon!' => '',
|
||||
'Default' => '',
|
||||
'Deny' => '',
|
||||
'Error' => 'Грешка',
|
||||
'Expand' => 'Разшири',
|
||||
'It looks like you may have taken the wrong turn.' => '',
|
||||
'Language' => 'Език',
|
||||
'Latest news' => 'Последни новини',
|
||||
'Login' => 'Вход',
|
||||
'Logout' => 'Изход',
|
||||
'Menu' => 'Меню',
|
||||
'Module is not on this content container enabled!' => '',
|
||||
'My profile' => 'Моят Профил',
|
||||
'New profile image' => 'Нова профилна картинка',
|
||||
'Next' => '',
|
||||
'Ok' => '',
|
||||
'Oooops...' => 'Опаля...',
|
||||
'Please type at least 3 characters' => '',
|
||||
'Save' => 'Запази',
|
||||
'Search' => 'Търси',
|
||||
'Search for users and spaces' => 'Търси хора и зони',
|
||||
'Space not found!' => 'Зоната не е открита!',
|
||||
'User not found!' => 'Потребителя не е намерен!',
|
||||
'Your daily summary' => '',
|
||||
);
|
||||
|
@ -1,21 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Message translations.
|
||||
*
|
||||
* This file is automatically generated by 'yiic 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 array (
|
||||
'Global {global} array cleaned using {method} method.' => '',
|
||||
);
|
File diff suppressed because one or more lines are too long
@ -1,56 +1,37 @@
|
||||
<?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 [
|
||||
'Allow' => '',
|
||||
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '',
|
||||
'Could not determine content container!' => '',
|
||||
'Could not find content of addon!' => '',
|
||||
'Default' => '',
|
||||
'Deny' => '',
|
||||
'It looks like you may have taken the wrong turn.' => '',
|
||||
'Module is not on this content container enabled!' => '',
|
||||
'Next' => '',
|
||||
'Please type at least 3 characters' => '',
|
||||
'Save' => '',
|
||||
'<strong>Latest</strong> updates' => '<strong>Últimes</strong> actualitzacions',
|
||||
'Account settings' => 'Configuració del compte',
|
||||
'Administration' => 'Administració',
|
||||
'Back' => 'Enrere',
|
||||
'Back to dashboard' => 'Torna a la portada',
|
||||
'Choose language:' => 'Escull un idioma:',
|
||||
'Collapse' => 'Redueix',
|
||||
'Error' => 'Error',
|
||||
'Expand' => 'Amplia',
|
||||
'Insufficent permissions to create content!' => 'Permisos insuficients per crear contingut!',
|
||||
'Language' => 'Llengua',
|
||||
'Latest news' => 'Últimes notícies',
|
||||
'Login' => 'Inici de sessió',
|
||||
'Logout' => 'Sortir',
|
||||
'Menu' => 'Menú',
|
||||
'My profile' => 'El meu perfil',
|
||||
'New profile image' => 'Nova imatge de perfil',
|
||||
'Oooops...' => 'Oooops...',
|
||||
'Search' => 'Cerca',
|
||||
'Search for users and spaces' => 'Cerca per membres i espais',
|
||||
'Space not found!' => 'Espai no trobat!',
|
||||
'User Approvals' => 'Aprovacions de membres',
|
||||
'User not found!' => 'Membre no trobat!',
|
||||
'You cannot create public visible content!' => 'No pots crear contingut públic visible!',
|
||||
'Your daily summary' => 'El teu resum diari',
|
||||
];
|
||||
return array (
|
||||
'<strong>Latest</strong> updates' => '<strong>Últimes</strong> actualitzacions',
|
||||
'Account settings' => 'Configuració del compte',
|
||||
'Administration' => 'Administració',
|
||||
'Allow' => '',
|
||||
'Back' => 'Enrere',
|
||||
'Back to dashboard' => 'Torna a la portada',
|
||||
'Choose language:' => 'Escull un idioma:',
|
||||
'Collapse' => 'Redueix',
|
||||
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '',
|
||||
'Could not determine content container!' => '',
|
||||
'Could not find content of addon!' => '',
|
||||
'Default' => '',
|
||||
'Deny' => '',
|
||||
'Error' => 'Error',
|
||||
'Expand' => 'Amplia',
|
||||
'It looks like you may have taken the wrong turn.' => '',
|
||||
'Language' => 'Llengua',
|
||||
'Latest news' => 'Últimes notícies',
|
||||
'Login' => 'Inici de sessió',
|
||||
'Logout' => 'Sortir',
|
||||
'Menu' => 'Menú',
|
||||
'Module is not on this content container enabled!' => '',
|
||||
'My profile' => 'El meu perfil',
|
||||
'New profile image' => 'Nova imatge de perfil',
|
||||
'Next' => 'Següent',
|
||||
'Ok' => 'D\'acord',
|
||||
'Oooops...' => 'Oooops...',
|
||||
'Please type at least 3 characters' => '',
|
||||
'Save' => 'Desa',
|
||||
'Search' => 'Cerca',
|
||||
'Search for users and spaces' => 'Cerca per membres i espais',
|
||||
'Space not found!' => 'Espai no trobat!',
|
||||
'User not found!' => 'Membre no trobat!',
|
||||
'Your daily summary' => 'El teu resum diari',
|
||||
);
|
||||
|
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
return array (
|
||||
'Global {global} array cleaned using {method} method.' => 'S\'ha netejat la cadena {global} utilitzant el mètode {method}.',
|
||||
);
|
File diff suppressed because one or more lines are too long
@ -1,56 +1,37 @@
|
||||
<?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 [
|
||||
'<strong>Latest</strong> updates' => '<strong>Poslední</strong> události',
|
||||
'Account settings' => 'Nastavení účtu',
|
||||
'Administration' => 'Administrace',
|
||||
'Allow' => 'Povolit',
|
||||
'Back' => 'Zpět',
|
||||
'Back to dashboard' => 'Zpět na nástěnku',
|
||||
'Choose language:' => 'Vyberte jazyk:',
|
||||
'Collapse' => 'Sbalit',
|
||||
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Content Addon musí být buď instancí objektu HActiveRecordContent nebo HActiveRecordContentAddon!',
|
||||
'Could not determine content container!' => 'Obsah nenalezen!',
|
||||
'Could not find content of addon!' => 'Nebylo možné nalézt obsah dolpňku!',
|
||||
'Default' => 'Výchozí',
|
||||
'Deny' => 'Odmítnout',
|
||||
'Error' => 'Chyba',
|
||||
'Expand' => 'Rozbalit',
|
||||
'Insufficent permissions to create content!' => 'Nedostatečná práva pro vytvoření obsahu!',
|
||||
'It looks like you may have taken the wrong turn.' => 'Zdá se, že jste někde špatně odbočili.',
|
||||
'Language' => 'Jazyk',
|
||||
'Latest news' => 'Poslední události',
|
||||
'Login' => 'Přihlásit se',
|
||||
'Logout' => 'Odhlásit',
|
||||
'Menu' => 'Menu',
|
||||
'Module is not on this content container enabled!' => 'Modul nebyl nalezen nebo je vypnut!',
|
||||
'My profile' => 'Můj profil',
|
||||
'New profile image' => 'Nový profilový obrázek',
|
||||
'Next' => 'Další',
|
||||
'Oooops...' => 'Jejda...',
|
||||
'Please type at least 3 characters' => 'Napište prosím alespoň 3 znaky',
|
||||
'Save' => 'Uložit',
|
||||
'Search' => 'Hledat',
|
||||
'Search for users and spaces' => 'Hledat mezi uživateli a prostory',
|
||||
'Space not found!' => 'Prostor nebyl nalezen!',
|
||||
'User Approvals' => 'Uživatelská oprávnění',
|
||||
'User not found!' => 'Uživatel nebyl nalezen!',
|
||||
'You cannot create public visible content!' => 'Nemůžete vytvářet veřejně viditelný obsah!',
|
||||
'Your daily summary' => 'Vaše denní shrnutí',
|
||||
];
|
||||
return array (
|
||||
'<strong>Latest</strong> updates' => '<strong>Poslední</strong> události',
|
||||
'Account settings' => 'Nastavení účtu',
|
||||
'Administration' => 'Administrace',
|
||||
'Allow' => 'Povolit',
|
||||
'Back' => 'Zpět',
|
||||
'Back to dashboard' => 'Zpět na nástěnku',
|
||||
'Choose language:' => 'Vyberte jazyk:',
|
||||
'Collapse' => 'Sbalit',
|
||||
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Content Addon musí být buď instancí objektu HActiveRecordContent nebo HActiveRecordContentAddon!',
|
||||
'Could not determine content container!' => 'Obsah nenalezen!',
|
||||
'Could not find content of addon!' => 'Nebylo možné nalézt obsah dolpňku!',
|
||||
'Default' => 'Výchozí',
|
||||
'Deny' => 'Odmítnout',
|
||||
'Error' => 'Chyba',
|
||||
'Expand' => 'Rozbalit',
|
||||
'It looks like you may have taken the wrong turn.' => 'Zdá se, že jste někde špatně odbočili.',
|
||||
'Language' => 'Jazyk',
|
||||
'Latest news' => 'Poslední události',
|
||||
'Login' => 'Přihlásit se',
|
||||
'Logout' => 'Odhlásit',
|
||||
'Menu' => 'Menu',
|
||||
'Module is not on this content container enabled!' => 'Modul nebyl nalezen nebo je vypnut!',
|
||||
'My profile' => 'Můj profil',
|
||||
'New profile image' => 'Nový profilový obrázek',
|
||||
'Next' => 'Další',
|
||||
'Ok' => 'Ok',
|
||||
'Oooops...' => 'Jejda...',
|
||||
'Please type at least 3 characters' => 'Napište prosím alespoň 3 znaky',
|
||||
'Save' => 'Uložit',
|
||||
'Search' => 'Hledat',
|
||||
'Search for users and spaces' => 'Hledat mezi uživateli a prostory',
|
||||
'Space not found!' => 'Prostor nebyl nalezen!',
|
||||
'User not found!' => 'Uživatel nebyl nalezen!',
|
||||
'Your daily summary' => 'Vaše denní shrnutí',
|
||||
);
|
||||
|
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
return array (
|
||||
'Global {global} array cleaned using {method} method.' => 'Globální pole {global} bylo vyčištěno pomocí metody {method}.',
|
||||
);
|
File diff suppressed because one or more lines are too long
@ -1,56 +1,37 @@
|
||||
<?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 [
|
||||
'<strong>Latest</strong> updates' => '<strong>Nyeste</ strong> opdateringer',
|
||||
'Account settings' => 'Kontoindstillinger',
|
||||
'Administration' => 'Administration',
|
||||
'Allow' => 'Tillad',
|
||||
'Back' => 'Tilbage',
|
||||
'Back to dashboard' => 'Tilbage til dashboard',
|
||||
'Choose language:' => 'Vælg sprog:',
|
||||
'Collapse' => 'Kollaps',
|
||||
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Indholdskilde addon skal være del en af HActiveRecordContent eller HActiveRecordContentAddon!',
|
||||
'Could not determine content container!' => 'Kunne ikke fastslå indholdscontainer!',
|
||||
'Could not find content of addon!' => 'Kunne ikke finde addonindhold!',
|
||||
'Default' => 'Standard',
|
||||
'Deny' => 'Afslå',
|
||||
'Error' => 'Fejl',
|
||||
'Expand' => 'Udvid',
|
||||
'Insufficent permissions to create content!' => 'Utilstrækkelige tilladelser til at skabe indhold!',
|
||||
'It looks like you may have taken the wrong turn.' => 'Det ser ud som du måske har taget den forkerte drejning.',
|
||||
'Language' => 'Sprog',
|
||||
'Latest news' => 'Sidste nyt',
|
||||
'Login' => 'Log ind',
|
||||
'Logout' => 'Log ud',
|
||||
'Menu' => 'Menu',
|
||||
'Module is not on this content container enabled!' => 'Modulet er ikke aktiveret i denne indholdscontainer!',
|
||||
'My profile' => 'Min profil',
|
||||
'New profile image' => 'Nyt profilbillede',
|
||||
'Next' => 'Næste',
|
||||
'Oooops...' => 'Hovsa...',
|
||||
'Please type at least 3 characters' => 'Venligst indtast mindst 3 tegn',
|
||||
'Save' => 'Gem',
|
||||
'Search' => 'Søg',
|
||||
'Search for users and spaces' => 'Søg efter brugere eller sider',
|
||||
'Space not found!' => 'Side ikke fundet!',
|
||||
'User Approvals' => 'Bruger godkendelser',
|
||||
'User not found!' => 'Bruger ikke fundet!',
|
||||
'You cannot create public visible content!' => 'Du kan ikke oprette offentlig synligt indhold!',
|
||||
'Your daily summary' => 'Dit daglige resumé',
|
||||
];
|
||||
return array (
|
||||
'<strong>Latest</strong> updates' => '<strong>Nyeste</ strong> opdateringer',
|
||||
'Account settings' => 'Kontoindstillinger',
|
||||
'Administration' => 'Administration',
|
||||
'Allow' => 'Tillad',
|
||||
'Back' => 'Tilbage',
|
||||
'Back to dashboard' => 'Tilbage til dashboard',
|
||||
'Choose language:' => 'Vælg sprog:',
|
||||
'Collapse' => 'Kollaps',
|
||||
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Indholdskilde addon skal være del en af HActiveRecordContent eller HActiveRecordContentAddon!',
|
||||
'Could not determine content container!' => 'Kunne ikke fastslå indholdscontainer!',
|
||||
'Could not find content of addon!' => 'Kunne ikke finde addonindhold!',
|
||||
'Default' => 'Standard',
|
||||
'Deny' => 'Afslå',
|
||||
'Error' => 'Fejl',
|
||||
'Expand' => 'Udvid',
|
||||
'It looks like you may have taken the wrong turn.' => 'Det ser ud som du måske har taget den forkerte drejning.',
|
||||
'Language' => 'Sprog',
|
||||
'Latest news' => 'Sidste nyt',
|
||||
'Login' => 'Log ind',
|
||||
'Logout' => 'Log ud',
|
||||
'Menu' => 'Menu',
|
||||
'Module is not on this content container enabled!' => 'Modulet er ikke aktiveret i denne indholdscontainer!',
|
||||
'My profile' => 'Min profil',
|
||||
'New profile image' => 'Nyt profilbillede',
|
||||
'Next' => 'Næste',
|
||||
'Ok' => 'Ok',
|
||||
'Oooops...' => 'Hovsa...',
|
||||
'Please type at least 3 characters' => 'Venligst indtast mindst 3 tegn',
|
||||
'Save' => 'Gem',
|
||||
'Search' => 'Søg',
|
||||
'Search for users and spaces' => 'Søg efter brugere eller sider',
|
||||
'Space not found!' => 'Side ikke fundet!',
|
||||
'User not found!' => 'Bruger ikke fundet!',
|
||||
'Your daily summary' => 'Dit daglige resumé',
|
||||
);
|
||||
|
@ -1,4 +0,0 @@
|
||||
<?php
|
||||
return array (
|
||||
'Global {global} array cleaned using {method} method.' => 'Global {global} array er rengjort ved brug af {method} metode.',
|
||||
);
|
File diff suppressed because one or more lines are too long
@ -1,56 +1,37 @@
|
||||
<?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 [
|
||||
'<strong>Latest</strong> updates' => '<strong>Letzte</strong> Aktualisierungen',
|
||||
'Account settings' => 'Kontoeinstellungen',
|
||||
'Administration' => 'Administration',
|
||||
'Allow' => 'Erlauben',
|
||||
'Back' => 'Zurück',
|
||||
'Back to dashboard' => 'Zurück zur Übersicht',
|
||||
'Choose language:' => 'Sprache wählen:',
|
||||
'Collapse' => 'Einklappen',
|
||||
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Die Quelle des Addons muss eine Instanz von HActiveRecordContent oder HActiveRecordContentAddon sein!',
|
||||
'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',
|
||||
'Error' => 'Fehler',
|
||||
'Expand' => 'Erweitern',
|
||||
'Insufficent permissions to create content!' => 'Unzureichende Berechtigungen um Inhalte zu erstellen!',
|
||||
'It looks like you may have taken the wrong turn.' => 'Du hast womöglich den falschen Weg eingeschlagen.',
|
||||
'Language' => 'Sprache',
|
||||
'Latest news' => 'Neuigkeiten',
|
||||
'Login' => 'Anmelden',
|
||||
'Logout' => 'Ausloggen',
|
||||
'Menu' => 'Menü',
|
||||
'Module is not on this content container enabled!' => 'Dieses Modul ist in diesem Content Container nicht aktiviert!',
|
||||
'My profile' => 'Mein Profil',
|
||||
'New profile image' => 'Neues Profilbild',
|
||||
'Next' => 'Nächster',
|
||||
'Oooops...' => 'Uuuups...',
|
||||
'Please type at least 3 characters' => 'Bitte wengistens 3 Zeichen eingeben',
|
||||
'Save' => 'Speichern',
|
||||
'Search' => 'Suchen',
|
||||
'Search for users and spaces' => 'Suche nach Benutzern und Spaces',
|
||||
'Space not found!' => 'Space nicht gefunden!',
|
||||
'User Approvals' => 'Benutzerfreigaben',
|
||||
'User not found!' => 'Benutzer nicht gefunden!',
|
||||
'You cannot create public visible content!' => 'Du hast nicht genügend Rechte um öffentlich sichtbaren Inhalt zu erstellen!',
|
||||
'Your daily summary' => 'Deine tägliche Übersicht',
|
||||
];
|
||||
return array (
|
||||
'<strong>Latest</strong> updates' => '<strong>Letzte</strong> Aktualisierungen',
|
||||
'Account settings' => 'Kontoeinstellungen',
|
||||
'Administration' => 'Administration',
|
||||
'Allow' => 'Erlauben',
|
||||
'Back' => 'Zurück',
|
||||
'Back to dashboard' => 'Zurück zur Übersicht',
|
||||
'Choose language:' => 'Sprache wählen:',
|
||||
'Collapse' => 'Einklappen',
|
||||
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Die Quelle des Addons muss eine Instanz von HActiveRecordContent oder HActiveRecordContentAddon sein!',
|
||||
'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',
|
||||
'Error' => 'Fehler',
|
||||
'Expand' => 'Erweitern',
|
||||
'It looks like you may have taken the wrong turn.' => 'Du hast womöglich den falschen Weg eingeschlagen.',
|
||||
'Language' => 'Sprache',
|
||||
'Latest news' => 'Neuigkeiten',
|
||||
'Login' => 'Anmelden',
|
||||
'Logout' => 'Ausloggen',
|
||||
'Menu' => 'Menü',
|
||||
'Module is not on this content container enabled!' => 'Dieses Modul ist in diesem Content Container nicht aktiviert!',
|
||||
'My profile' => 'Mein Profil',
|
||||
'New profile image' => 'Neues Profilbild',
|
||||
'Next' => 'Nächster',
|
||||
'Ok' => 'Ok',
|
||||
'Oooops...' => 'Uuuups...',
|
||||
'Please type at least 3 characters' => 'Bitte wengistens 3 Zeichen eingeben',
|
||||
'Save' => 'Speichern',
|
||||
'Search' => 'Suchen',
|
||||
'Search for users and spaces' => 'Suche nach Benutzern und Spaces',
|
||||
'Space not found!' => 'Space nicht gefunden!',
|
||||
'User not found!' => 'Benutzer nicht gefunden!',
|
||||
'Your daily summary' => 'Deine tägliche Übersicht',
|
||||
);
|
||||
|
@ -1,21 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Message translations.
|
||||
*
|
||||
* This file is automatically generated by 'yiic 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 array (
|
||||
'Global {global} array cleaned using {method} method.' => 'Das globale {global} Array wurde mit der {method} Methode bereinigt.',
|
||||
);
|
@ -1,22 +0,0 @@
|
||||
<?php
|
||||
/**
|
||||
* Message translations.
|
||||
*
|
||||
* This file is automatically generated by 'yiic 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 array (
|
||||
'<strong>Upload</strong> error' => '<strong>Hochladen</strong> fehlgeschlagen',
|
||||
'Close' => 'Schließen',
|
||||
);
|
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
Loading…
x
Reference in New Issue
Block a user