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

This commit is contained in:
buddha87 2016-06-05 20:06:27 +02:00
commit 08fea57851
6135 changed files with 62112 additions and 59698 deletions

View File

@ -23,6 +23,7 @@
"cebe/markdown": "1.0.2", "cebe/markdown": "1.0.2",
"yiisoft/yii2-jui": "^2.0", "yiisoft/yii2-jui": "^2.0",
"zendframework/zend-http": "*", "zendframework/zend-http": "*",
"jbroadway/urlify": "^1.0",
"nqxcode/zendsearch": "^2.0", "nqxcode/zendsearch": "^2.0",
"xj/yii2-jplayer-widget": "*", "xj/yii2-jplayer-widget": "*",
"zendframework/zend-ldap": "^2.5", "zendframework/zend-ldap": "^2.5",

View File

@ -125,11 +125,23 @@ function HashTable(obj) {
/** /**
* setModalLoader * To allow other frameworks to overlay focusable nodes over an active modal we have
* * to explicitly allow ith within this overwritten function.
* Change buttons with loader
* *
*/ */
$.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() { function setModalLoader() {
$(".modal-footer .btn").hide(); $(".modal-footer .btn").hide();
$(".modal-footer .loader").removeClass("hidden"); $(".modal-footer .loader").removeClass("hidden");
@ -143,14 +155,53 @@ $(document).ready(function () {
$(this).removeData('bs.modal'); $(this).removeData('bs.modal');
// just close modal and reset modal content to default (shows the loader) // 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 // set Modal handler to all modal links
setModalHandler(); setModalHandler();
initPlugins(); 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() { function setModalHandler() {
@ -162,7 +213,7 @@ function setModalHandler() {
$(document).on('click.humhub', "a[data-target='#globalModal']", function (ev) { $(document).on('click.humhub', "a[data-target='#globalModal']", function (ev) {
ev.preventDefault(); ev.preventDefault();
var options = { var options = {
'show' : true, 'show': true,
'backdrop': $(this).data('backdrop') 'backdrop': $(this).data('backdrop')
} }
$("#globalModal").modal(options); $("#globalModal").modal(options);

36
js/select2-extension.js Normal file
View 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
View 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');
}
});
});

View 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'
];
}

View 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'];
}

View File

@ -15,7 +15,7 @@ use humhub\models\Setting;
/** /**
* Cronjobs * Cronjobs
* *
* @author Luke * @author Luke
*/ */
class CronController extends Controller class CronController extends Controller
@ -41,7 +41,7 @@ class CronController extends Controller
$this->trigger(self::EVENT_ON_HOURLY_RUN); $this->trigger(self::EVENT_ON_HOURLY_RUN);
$this->stdout("\n\nAll cron tasks finished.\n\n", Console::FG_GREEN); $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; return self::EXIT_CODE_NORMAL;
} }
@ -56,7 +56,7 @@ class CronController extends Controller
$this->trigger(self::EVENT_ON_DAILY_RUN); $this->trigger(self::EVENT_ON_DAILY_RUN);
$this->stdout("\n\nAll cron tasks finished.\n\n", Console::FG_GREEN); $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; return self::EXIT_CODE_NORMAL;
} }

View File

@ -162,7 +162,7 @@ class HForm extends \yii\base\Component
$output = ""; $output = "";
foreach ($buttons as $buttonName => $definition) { foreach ($buttons as $buttonName => $definition) {
if ($definition['type'] == 'submit') { 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 .= "&nbsp;"; $output .= "&nbsp;";
} }
} }
@ -193,6 +193,7 @@ class HForm extends \yii\base\Component
if (isset($definition['readonly']) && $definition['readonly']) { if (isset($definition['readonly']) && $definition['readonly']) {
$options['readOnly'] = true; $options['readOnly'] = true;
$options['disabled'] = true;
} }
if (isset($definition['value'])) { if (isset($definition['value'])) {

View File

@ -31,7 +31,7 @@ class Application extends \yii\web\Application
* Check if it's already installed - if not force controller module * Check if it's already installed - if not force controller module
*/ */
if (!$this->params['installed'] && $this->controller->module != null && $this->controller->module->id != 'installer') { 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; return false;
} }

View File

@ -33,6 +33,20 @@ class Module extends \yii\base\Module
*/ */
public $resourcesPath = 'assets'; 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 * Returns modules name provided by module.json file
* *
@ -82,7 +96,7 @@ class Module extends \yii\base\Module
/** /**
* Returns image url for this 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 * @return String Image Url
*/ */
@ -91,7 +105,8 @@ class Module extends \yii\base\Module
$moduleImageFile = $this->getBasePath() . '/' . $this->resourcesPath . '/module_image.png'; $moduleImageFile = $this->getBasePath() . '/' . $this->resourcesPath . '/module_image.png';
if (is_file($moduleImageFile)) { 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"); return Yii::getAlias("@web/img/default_module.jpg");
@ -110,20 +125,14 @@ class Module extends \yii\base\Module
/** /**
* Enables this module * Enables this module
* It will be available on the next request.
* *
* @return boolean * @return boolean
*/ */
public function enable() public function enable()
{ {
$moduleEnabled = ModuleEnabled::findOne(['module_id' => $this->id]); Yii::$app->moduleManager->enable($this);
if ($moduleEnabled == null) {
$moduleEnabled = new ModuleEnabled();
$moduleEnabled->module_id = $this->id;
$moduleEnabled->save();
}
$this->migrate(); $this->migrate();
return true; return true;
} }
@ -135,11 +144,7 @@ class Module extends \yii\base\Module
*/ */
public function disable() public function disable()
{ {
// Disable module in database
$moduleEnabled = ModuleEnabled::findOne(['module_id' => $this->id]);
if ($moduleEnabled != null) {
$moduleEnabled->delete();
}
/** /**
* Remove database tables * 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();
}
/* foreach (\humhub\models\Setting::findAll(['module_id' => $this->id]) as $containerSetting) {
HSetting::model()->deleteAllByAttributes(array('module_id' => $this->getId())); $containerSetting->delete();
SpaceSetting::model()->deleteAllByAttributes(array('module_id' => $this->getId())); }
UserSetting::model()->deleteAllByAttributes(array('module_id' => $this->getId()));
// Delete also records with disabled state from SpaceApplicationModule Table foreach (\humhub\modules\user\models\Module::findAll(['module_id' => $this->id]) as $userModule) {
foreach (SpaceApplicationModule::model()->findAllByAttributes(array('module_id' => $this->getId())) as $sam) { $userModule->delete();
$sam->delete(); }
}
// Delete also records with disabled state from UserApplicationModule Table foreach (\humhub\modules\space\models\Module::findAll(['module_id' => $this->id]) as $spaceModule) {
foreach (UserApplicationModule::model()->findAllByAttributes(array('module_id' => $this->getId())) as $uam) { $spaceModule->delete();
$uam->delete(); }
}
ModuleManager::flushCache(); Yii::$app->moduleManager->disable($this);
*/
} }
/** /**
@ -251,7 +255,7 @@ class Module extends \yii\base\Module
{ {
return []; return [];
} }
/** /**
* Returns a list of notification classes this module provides. * Returns a list of notification classes this module provides.
* *

View File

@ -13,6 +13,7 @@ use yii\base\Exception;
use yii\base\Event; use yii\base\Event;
use yii\base\InvalidConfigException; use yii\base\InvalidConfigException;
use humhub\components\bootstrap\ModuleAutoLoader; use humhub\components\bootstrap\ModuleAutoLoader;
use humhub\models\ModuleEnabled;
/** /**
* ModuleManager handles all installed modules. * ModuleManager handles all installed modules.
@ -114,6 +115,8 @@ class ModuleManager extends \yii\base\Component
if (isset($config['namespace'])) { if (isset($config['namespace'])) {
Yii::setAlias('@' . str_replace('\\', '/', $config['namespace']), $basePath); Yii::setAlias('@' . str_replace('\\', '/', $config['namespace']), $basePath);
} }
Yii::setAlias('@' . $config['id'], $basePath);
if (!Yii::$app->params['installed'] && $isInstallerModule) { if (!Yii::$app->params['installed'] && $isInstallerModule) {
$this->enabledModules[] = $config['id']; $this->enabledModules[] = $config['id'];
@ -145,14 +148,12 @@ class ModuleManager extends \yii\base\Component
// Add config file values to module // Add config file values to module
if (isset(Yii::$app->modules[$config['id']]) && is_array(Yii::$app->modules[$config['id']])) { 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 // Register Yii Module
Yii::$app->setModule($config['id'], $moduleConfig); Yii::$app->setModule($config['id'], $moduleConfig);
// Register Event Handlers // Register Event Handlers
if (isset($config['events'])) { if (isset($config['events'])) {
foreach ($config['events'] as $event) { foreach ($config['events'] as $event) {
@ -295,13 +296,52 @@ class ModuleManager extends \yii\base\Component
$backupFolderName = $moduleBackupFolder . DIRECTORY_SEPARATOR . $moduleId . "_" . time(); $backupFolderName = $moduleBackupFolder . DIRECTORY_SEPARATOR . $moduleId . "_" . time();
if (!@rename($module->getBasePath(), $backupFolderName)) { 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 { } else {
//TODO: Delete directory //TODO: Delete directory
} }
$this->flushCache(); $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');
}
} }

View File

@ -12,8 +12,8 @@ use Yii;
/** /**
* @inheritdoc * @inheritdoc
* *
* *
* @author luke * @author luke
*/ */
class Request extends \yii\web\Request class Request extends \yii\web\Request
@ -25,10 +25,10 @@ class Request extends \yii\web\Request
public function init() public function init()
{ {
if (\humhub\models\Setting::isInstalled()) { if (\humhub\models\Setting::isInstalled()) {
$secret = \humhub\models\Setting::Get('secret'); $secret = Yii::$app->settings->get('secret');
if ($secret != "") { if ($secret != "") {
$this->cookieValidationKey = \humhub\models\Setting::Get('secret'); $this->cookieValidationKey = $secret;
} }
} else { } else {
$this->cookieValidationKey = 'installer'; $this->cookieValidationKey = 'installer';
} }

View 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);
}
}

View 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]) . '"';
}
}

View File

@ -10,6 +10,7 @@ namespace humhub\components;
use Yii; use Yii;
use yii\helpers\FileHelper; use yii\helpers\FileHelper;
use humhub\libs\ThemeHelper;
use humhub\models\Setting; use humhub\models\Setting;
/** /**
@ -20,7 +21,7 @@ class Theme extends \yii\base\Theme
/** /**
* Name of the Theme * Name of the Theme
* *
* @var string * @var string
*/ */
public $name; public $name;
@ -30,6 +31,11 @@ class Theme extends \yii\base\Theme
*/ */
private $_baseUrl = null; private $_baseUrl = null;
/**
* Indicates that resources should be published via assetManager
*/
public $publishResources = false;
/** /**
* @inheritdoc * @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 * @inheritdoc
* to be under this base URL.
*/ */
public function getBaseUrl() public function getBaseUrl()
{ {
if ($this->_baseUrl !== null) { if ($this->_baseUrl !== null) {
return $this->_baseUrl; 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; 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 * @inheritdoc
*/ */
public function applyTo($path) public function applyTo($path)
{ {
$autoPath = $this->autoFindModuleView($path); $autoPath = $this->autoFindModuleView($path);
if ($autoPath !== null && file_exists($autoPath)) { if ($autoPath !== null && file_exists($autoPath)) {
return $autoPath; return $autoPath;
@ -84,9 +100,28 @@ class Theme extends \yii\base\Theme
return parent::applyTo($path); 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. * Tries to automatically maps the view file of a module to a themed one.
* *
* Formats: * Formats:
* .../moduleId/views/controllerId/viewName.php * .../moduleId/views/controllerId/viewName.php
@ -96,7 +131,7 @@ class Theme extends \yii\base\Theme
* .../moduleId/[widgets|activities|notifications]/views/viewName.php * .../moduleId/[widgets|activities|notifications]/views/viewName.php
* to: * to:
* .../views/moduleId/[widgets|activities|notifications]/viewName.php * .../views/moduleId/[widgets|activities|notifications]/viewName.php
* *
* @return string theme view path or null * @return string theme view path or null
*/ */
protected function autoFindModuleView($path) protected function autoFindModuleView($path)
@ -122,113 +157,13 @@ class Theme extends \yii\base\Theme
} }
/** /**
* Returns an array of all installed themes. * Stores color informations to configuration for use in modules.
*
* @return Array Theme instances
*/ */
public static function getThemes() public function storeColorsToConfig()
{ {
$themes = array(); $lessFileName = $this->getBasePath() . '/css/theme.less';
$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');
if (file_exists($lessFileName)) { if (file_exists($lessFileName)) {
$file = fopen($lessFileName, "r") or die("Unable to open file!"); $less = file_get_contents($lessFileName);
$less = fread($file, filesize($lessFileName));
fclose($file);
$startDefault = strpos($less, '@default') + 10; $startDefault = strpos($less, '@default') + 10;
$startPrimary = strpos($less, '@primary') + 10; $startPrimary = strpos($less, '@primary') + 10;
@ -238,12 +173,27 @@ class Theme extends \yii\base\Theme
$startDanger = strpos($less, '@danger') + 9; $startDanger = strpos($less, '@danger') + 9;
$length = 7; $length = 7;
Setting::Set('colorDefault', substr($less, $startDefault, $length)); Yii::$app->settings->set('colorDefault', substr($less, $startDefault, $length));
Setting::Set('colorPrimary', substr($less, $startPrimary, $length)); Yii::$app->settings->set('colorPrimary', substr($less, $startPrimary, $length));
Setting::Set('colorInfo', substr($less, $startInfo, $length)); Yii::$app->settings->set('colorInfo', substr($less, $startInfo, $length));
Setting::Set('colorSuccess', substr($less, $startSuccess, $length)); Yii::$app->settings->set('colorSuccess', substr($less, $startSuccess, $length));
Setting::Set('colorWarning', substr($less, $startWarning, $length)); Yii::$app->settings->set('colorWarning', substr($less, $startWarning, $length));
Setting::Set('colorDanger', substr($less, $startDanger, $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();
} }
} }

View File

@ -44,25 +44,26 @@ class AccessControl extends \yii\base\ActionFilter
*/ */
public function beforeAction($action) public function beforeAction($action)
{ {
$identity = Yii::$app->user->getIdentity(); $identity = Yii::$app->user->getIdentity();
if($identity != null && !$identity->isActive()) { if($identity != null && !$identity->isActive()) {
Yii::$app->user->logout(); 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 (Yii::$app->user->isGuest) {
if (!$this->loggedInOnly && !$this->adminOnly) { if (!$this->loggedInOnly && !$this->adminOnly) {
return true; 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; return true;
} }
Yii::$app->user->loginRequired(); Yii::$app->user->loginRequired();
return false; return false;
} }
if ($this->adminOnly && !Yii::$app->user->isAdmin()) { if ($this->adminOnly && !Yii::$app->user->isAdmin()) {
$this->forbidden(); $this->forbidden();
} }

View File

@ -38,8 +38,8 @@ class ModuleAutoLoader implements BootstrapInterface
if (is_dir($moduleDir) && is_file($moduleDir . DIRECTORY_SEPARATOR . 'config.php')) { if (is_dir($moduleDir) && is_file($moduleDir . DIRECTORY_SEPARATOR . 'config.php')) {
try { try {
$modules[$moduleDir] = require($moduleDir . DIRECTORY_SEPARATOR . 'config.php'); $modules[$moduleDir] = require($moduleDir . DIRECTORY_SEPARATOR . 'config.php');
} catch (Exception $ex) { } catch (\Exception $ex) {
} }
} }
} }

View File

@ -2,7 +2,7 @@
/** /**
* @link https://www.humhub.org/ * @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 * @license https://www.humhub.com/licences
*/ */
@ -33,14 +33,20 @@ class Application extends \yii\console\Application
$this->trigger(self::EVENT_ON_INIT); $this->trigger(self::EVENT_ON_INIT);
if ($this->isDatabaseInstalled()) { if ($this->isDatabaseInstalled()) {
$baseUrl = Setting::get('baseUrl'); $baseUrl = Yii::$app->settings->get('baseUrl');
if ($baseUrl !== null) {
if($baseUrl != null) {
Yii::setAlias(("@web"), $baseUrl); Yii::setAlias(("@web"), $baseUrl);
$this->urlManager->scriptUrl = $baseUrl; $this->urlManager->scriptUrl = $baseUrl;
$this->urlManager->baseUrl = $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 * Checks if database is installed
* *
* @return boolean is database installed/migrated * @return boolean is database installed/migrated
*/ */
public function isDatabaseInstalled() public function isDatabaseInstalled()
@ -68,7 +74,7 @@ class Application extends \yii\console\Application
if (in_array('setting', Yii::$app->db->schema->getTableNames())) { if (in_array('setting', Yii::$app->db->schema->getTableNames())) {
return true; return true;
} }
return false; return false;
} }

View File

@ -8,6 +8,7 @@
namespace humhub\components\i18n; namespace humhub\components\i18n;
use Yii;
use humhub\models\Setting; use humhub\models\Setting;
/** /**
@ -20,7 +21,7 @@ class Formatter extends \yii\i18n\Formatter
* @inheritdoc * @inheritdoc
*/ */
public $sizeFormatBase = 1000; public $sizeFormatBase = 1000;
/** /**
* @var string the default format string to be used to format a input field [[asDate()|date]]. * @var string the default format string to be used to format a input field [[asDate()|date]].
* This mostly used in forms (DatePicker). * This mostly used in forms (DatePicker).
@ -35,8 +36,8 @@ class Formatter extends \yii\i18n\Formatter
{ {
parent::init(); parent::init();
if (Setting::Get('defaultDateInputFormat', 'admin') != '') { if (Yii::$app->getModule('admin')->settings->get('defaultDateInputFormat') != '') {
$this->dateInputFormat = Setting::Get('defaultDateInputFormat', 'admin'); $this->dateInputFormat = Yii::$app->getModule('admin')->settings->get('defaultDateInputFormat');
} }
} }

View File

@ -8,7 +8,7 @@ Yii::setAlias('@config', '@app/config');
$config = [ $config = [
'name' => 'HumHub', 'name' => 'HumHub',
'version' => '1.1.0-dev', 'version' => '1.2.0-dev',
'basePath' => dirname(__DIR__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR, 'basePath' => dirname(__DIR__) . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR,
'bootstrap' => ['log', 'humhub\components\bootstrap\ModuleAutoLoader'], 'bootstrap' => ['log', 'humhub\components\bootstrap\ModuleAutoLoader'],
'sourceLanguage' => 'en', 'sourceLanguage' => 'en',
@ -27,6 +27,7 @@ $config = [
[ [
'class' => 'yii\log\DbTarget', 'class' => 'yii\log\DbTarget',
'levels' => ['error', 'warning'], 'levels' => ['error', 'warning'],
'except' => ['yii\web\HttpException:404'],
'logVars' => ['_GET', '_SERVER'], 'logVars' => ['_GET', '_SERVER'],
], ],
], ],
@ -34,6 +35,10 @@ $config = [
'search' => array( 'search' => array(
'class' => 'humhub\modules\search\engine\ZendLuceneSearch', 'class' => 'humhub\modules\search\engine\ZendLuceneSearch',
), ),
'settings' => array(
'class' => 'humhub\components\SettingsManager',
'moduleId' => 'base',
),
'i18n' => [ 'i18n' => [
'class' => 'humhub\components\i18n\I18N', 'class' => 'humhub\components\i18n\I18N',
'translations' => [ 'translations' => [
@ -53,10 +58,6 @@ $config = [
'class' => 'yii\i18n\PhpMessageSource', 'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@humhub/messages' 'basePath' => '@humhub/messages'
], ],
'iso3166Codes' => [
'class' => 'yii\i18n\PhpMessageSource',
'basePath' => '@humhub/messages'
],
], ],
], ],
'formatter' => [ 'formatter' => [

View File

@ -5,7 +5,7 @@ return [
'sourcePath' => __DIR__ . DIRECTORY_SEPARATOR . '..', 'sourcePath' => __DIR__ . DIRECTORY_SEPARATOR . '..',
// array, required, list of language codes that the extracted messages // array, required, list of language codes that the extracted messages
// should be translated to. For example, ['zh-CN', 'de']. // 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. // 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 // 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 // translated. You may use a string for single function name or an array for

View File

@ -49,7 +49,7 @@ class ErrorController extends Controller
/** /**
* Show special login required view for guests * 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]); return $this->render('@humhub/views/error/401_guests', ['message' => $message]);
} }

View File

@ -5,18 +5,20 @@ Introduction
------------ ------------
* [About HumHub](intro-index.md) * [About HumHub](intro-index.md)
* [Licence](intro-licence.md) * [Licence](intro-licence.md)
* [Bundled Software](intro-bundled_software.md)
Administration Getting Started
--------------- ---------------
* [Requirements](admin-requirements.md) * [Requirements](admin-requirements.md)
* [Installation](admin-installation.md) * [Installation](admin-installation.md)
* [Updating](admin-updating.md) * [Updating](admin-updating.md)
Administration
---------------------
* [User](admin-user.md) * [User](admin-user.md)
* [Spaces](admin-spaces.md) * [Spaces](admin-spaces.md)
* [Authentication](admin-authentication.md)
Administration - Topics
-------------------------
* [Advanced Configuration](admin-adv-config.md) * [Advanced Configuration](admin-adv-config.md)
* [Console](admin-adv-console.md) * [Console](admin-adv-console.md)
* [Search](admin-adv-search.md) * [Search](admin-adv-search.md)
@ -27,34 +29,22 @@ Development
--------------------- ---------------------
* [Getting Started](dev-index.md) * [Getting Started](dev-index.md)
* [Updating / Migrate](dev-migrate.md) * [Update / Migration](dev-migrate.md)
* [Application Overview](dev-overview.md)
* [Content](dev-content.md) * [Content](dev-content.md)
* [Notification](dev-notifications.md) * [Permissions](dev-permissions.md)
* [Activities](dev-environment.md) * [Notifications](dev-notifications.md)
* [Search](dev-environment.md) * [Activities](dev-activities.md)
* [User](dev-environment.md) * [Streams](dev-stream.md)
* [Build](dev-environment.md) * [Events](dev-events.md)
* [Frontend](dev-javascript.md) * [Widgets](dev-widgets.md)
* [Contributions](dev-contributing.md) * [Internationalization](dev-i18n.md)
* [Authentication](dev-authentication.md)
* [Models / Database](dev-db.md)
Development - Modules * [Search](dev-search.md)
--------------------- * [CronJobs](dev-cron.md)
* [Settings and Configuration](dev-settings.md)
* [Getting Started](dev-module-index.md) * [Console Application](dev-console.md)
* [Events](dev-module-events.md) * [Module Development](dev-module.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)
Theming Theming
------- -------
@ -62,10 +52,3 @@ Theming
* [Getting Started](theming-index.md) * [Getting Started](theming-index.md)
* [Update / Migrate](theming-migrate.md) * [Update / Migrate](theming-migrate.md)
Special Topics
--------------
* [Translations](special-translations.md)
* [Bundled Software](special-bundled_software.md)

View File

@ -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;
},
],
],
],
],
// ..
],
// ...
```

View File

@ -66,7 +66,7 @@ config/messages/de/PostModule.widgets_views_postForm.php
with the content: with the content:
``` php ```php
<?php <?php
return array ( return array (
'What\'s on your mind?' => 'Wie geht es dir heute?', 'What\'s on your mind?' => 'Wie geht es dir heute?',

View 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.

View File

@ -1,7 +1,7 @@
Installation Installation
============ ============
## 1. Preparation ## Preparation
Create an MySQL Database, e.g.: Create an MySQL Database, e.g.:
@ -11,16 +11,31 @@ GRANT ALL ON `humhub`.* TO `humhub_dbuser`@localhost IDENTIFIED BY 'password_cha
FLUSH PRIVILEGES; 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 ### 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 - Clone Git Repository
``` ```
git clone https://github.com/humhub/humhub.git 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)) - Install composer ([https://getcomposer.org/doc/00-intro.md](https://getcomposer.org/doc/00-intro.md))
- Navigate to your HumHub webroot and fetch dependencies - 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 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. ## Setting up
## 3. Setting up
### File Modes / Permissions ### File Modes / Permissions
@ -48,19 +61,26 @@ Make the following files executable:
- /protected/yii - /protected/yii
- /protected/yii.bat - /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 ### Start Installer
Open installation in your browser (e.g. [http://localhost/humhub](http://localhost/humhub)) Open installation in your browser (e.g. [http://localhost/humhub](http://localhost/humhub))
## 4. Fine Tuning ## Fine Tuning
### E-Mail Configuration ### E-Mail Configuration
Depending on your environment which you are using you may want specify a local or remote SMTP Server. Depending on your environment you are using, you may want to specify a local or remote SMTP Server.
You can change this settings at `Administration -> Mailing -> Server Settings`. 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) ### Enable Url Rewriting (Optional)
@ -84,11 +104,8 @@ return [
### Enable Cron Jobs ### Enable Cron Jobs
Daily cron command: - Daily cron command: `> yii cron/daily`
> yii cron/daily - Hourly cron command: `> yii cron/hourly`
Hourly cron command:
> yii cron/hourly
Example Tab: Example Tab:
@ -97,15 +114,6 @@ Example Tab:
00 18 * * * /path/to/humhub/protected/yii cron/daily >/dev/null 2>&1 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 ### Disable Errors / Debugging
- Modify *index.php* in humhub root directory - Modify *index.php* in humhub root directory

View File

@ -7,7 +7,7 @@ A space can be used by space members to share content with other users.
## Add Spaces ## 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. 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_. Spaces can be added by clicking _Add Space_ within the _Space Navigation_.
A new space will require at least a space name. Futhermore you are able to define a space color, a description and advanced access settings. A new space will require at least a space name. Futhermore you are able to define a space color, a description and advanced access settings.

View File

@ -1,14 +1,16 @@
Updating 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! > NOTE: Only use this guide if you want to update from HumHub 0.20 or higher!
> If you want to update from an older version (e.g. 0.11.2 or lower) to HumHub 0.20+, you have to use this guide: **[Upgrade to 0.20 and above](admin-updating-020.md "Guide: Upgrade to 0.20 and above")** > If you want to update from an older version (e.g. 0.11.2 or lower) to HumHub 0.20+, you have to use this guide: **[Upgrade to 0.20 and above](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. > NOTE: Backup your data:
- Backup the whole HumHub installation folder from your webroot
2. Backup your data: - Make a complete MySQL Backup from your HumHub database
- Backup the whole HumHub installation folder from your webroot
- Make a complete MySQL Backup from your HumHub database
## Download Package installations ## Download Package installations

View File

@ -2,7 +2,7 @@ User
======= =======
##User Management ##User Management
Users can be managed under _Administration -> Users_. Users are managed under **Administration -> Users**.
###Overview: ###Overview:
@ -12,54 +12,43 @@ The _Overview_ lists all registrated users with actions to
- _Edit User_ - _Edit User_
- _Delete 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 ## 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: 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. 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. 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. 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. 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, 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 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. 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 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). 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. 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. 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_. Changes of this selection will only affect new users. It can either be set to _members only_ or _members and guests_.
##User Approval ##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.

View 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

View 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

View File

@ -0,0 +1,3 @@
Build
========
(TBD)

View 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();
}
}
}
}
```

View File

@ -3,8 +3,9 @@ Content
## ContentContainer ## 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]] in HumHub is the base concept for assigning content entries to a specific container instance (user or space).
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. 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: Currently there are two types of ContentContainer:
- [[humhub\modules\user\models\User|User]] - [[humhub\modules\user\models\User|User]]
@ -16,8 +17,8 @@ Currently there are two types of ContentContainer:
### ContentContainerController ### 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]]. 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 the associated [[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: 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) - Layout selection based on container type (User or Space)
- Create URL's for the given ContentContainer - Create URL's for the given ContentContainer
For example, For example:
```php ```php
class ExampleController extends \humhub\modules\content\components\ContentContainerController 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]]. Each ContentContainer class is derived from [[\humhub\modules\content\components\ContentContainerActiveRecord]].
Beside others, this abstract class provides the following functionality: Beside others, this abstract class provides the following functionality:
- Permission Management - [Permission Management](dev-permissions.md) `getPermissionManager()`
- Getter for Profile-/BannerImage - 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 ### 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. 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 the [[humhub\modules\content\components\ContentContainerModule]] class for a full list of options.
See [[humhub\modules\content\components\ContentContainerModule]] class for a full list of options.
Example of a modules `Module.php` file: 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 class Module extends \humhub\modules\content\components\ContentContainerModule
{ {
// Defines for which content container type this module is appropriate
public function getContentContainerTypes() public function getContentContainerTypes()
{ {
//This content container can be assigned to Spaces and User // This content container can be assigned to Spaces and User
return [ return [
Space::className(), Space::className(),
User::className(), User::className(),
]; ];
} }
// Is called when the whole module is disabled
public function disable() public function disable()
{ {
// Clear all Module data and call parent disable // Clear all Module data and call parent disable
parent::disable(); parent::disable();
} }
// Is called when the module is disabled on a specific container
public function disableContentContainer(ContentContainerActiveRecord $container) public function disableContentContainer(ContentContainerActiveRecord $container)
{ {
parent::disableContentContainer($container); parent::disableContentContainer($container);
//Here you can clear all data related to the given 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) public function getContentContainerDescription(ContentContainerActiveRecord $container)
{ {
if ($container instanceof Space) { 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 ## Content
@ -138,10 +138,10 @@ This Content record holds all neccessary informations and provides common method
- Archiving / Sticking - Archiving / Sticking
- And more... - 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) - `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. - `getContentDescription()` - Returns a preview of the Content - which is used in Notifications for example.
Example: Example:
@ -150,22 +150,17 @@ Example:
``` ```
#### Wall/Stream Output #### Wall/Stream Output
(TBD)
#### Querying Content #### 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 - contentContainer($container) - Find content only inside a given container
- readable($user) - Return only user readable content - readable($user) - Return only user readable content
- ... - ...
#### Permissions
TBD (Read Permissions not enhanceable)
### Controller ### Controller

View 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();
}
}
}
}
```

View File

@ -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',
],
// ...
];
```

View File

@ -6,9 +6,112 @@ Overview
- HumHub is based on Yii 2.0 PHP Framework (http://www.yiiframework.com/) - 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) - [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 ## Development Environment Notes
- Use Composer Installation include dev requirements - Use Composer Installation as described in the [Installation Guide](admin-installation.md#via-gitcomposer)
- Switch to development mode in ``index.php`` (see inline documentation) - Switch to development mode in ``index.php`` (described [here](admin-installation.md#disable-errors-debugging))
- Disable Caching (Administration -> Settings -> Caching -> None) - 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',
],
// ...
];
```

View File

@ -2,7 +2,7 @@
Here you will learn how you can adapt existing modules to working fine with actually versions. 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" - 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 - Not longer validates content visibility (private/public) permissions
- system_admin attribute in user table was removed - 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!** **Important: This release upgrades from Yii1 to Yii2 Framework!**
This requires an extensive migration of all custom modules/themes. This requires an extensive migration of all custom modules/themes.
Find more details here: [HumHub 0.20 Migration](dev-migrate-0.20.md) 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 - Rewritten Search
## to 0.11 ## Migrate from 0.10 to 0.11
No breaking changes. No breaking changes.
- Now handle ContentContainerController layouts, new option showSidebar - Now handle ContentContainerController layouts, new option showSidebar
- New ContentAddonController Class - New ContentAddonController Class
- New Wiki Parser / Editor Widget - New Wiki Parser / Editor Widget
## to 0.10
No breaking changes

View File

@ -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

View File

@ -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();
}
```

View File

@ -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;
}
}
```

View File

@ -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"
}
}
```

View File

@ -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,
));
}
}
//...
```

View File

@ -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");
```

View File

@ -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(),
];
}
// ...
}
```

View File

@ -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();
}
}
}
}
```

View File

@ -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));
}
```

View File

@ -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)); ?>
```

View 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"
}
}
```

View File

@ -1,15 +1,32 @@
Notifications 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) ![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
<?php <?php
@ -23,37 +40,45 @@ use humhub\modules\notification\components\BaseNotification;
*/ */
class SomethingHappend extends BaseNotification class SomethingHappend extends BaseNotification
{ {
// Module Id (required) // Module Id (required)
public $moduleId = "example"; public $moduleId = "example";
// Viewname (required)
public $viewName = "somethingHappend"; 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
<?php <?php
use yii\helpers\Html; 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>' '%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 ```php
$notification = new \johndoe\example\notifications\SomethingHappend(); $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; $notification->source = $this;
// The user which triggered the notification (optional) // The user which triggered the notification (optional)
@ -65,9 +90,14 @@ $notification->sendBulk(User::find()->where([...]));
// or: a single user // or: a single user
$notification->send($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. 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 = new johndoe\example\notifications\SomethingHappend();
$notification->source = $this; $notification->source = $this;
$notification->delete(User::findOne(['id' => $userId])); $notification->delete(User::findOne(['id' => $userId]));
``` ```

View File

@ -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)

View File

@ -0,0 +1,3 @@
Permissions
========
(TBD)

View File

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

View File

@ -0,0 +1,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)); ?>
```

View 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

View 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,
]);
}
}
//...
```

View File

@ -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();
}
```

View File

@ -1,4 +0,0 @@
User
====
TBD

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 46 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 53 KiB

View File

@ -2,12 +2,26 @@
Here you will learn how you can adapt existing themes to working fine with actually versions. 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: 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 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/**. 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. 6. Check if everything works well, and fix optical issues at your theme file, if necessery.
## Migrate from 0.9 to 10.0
---
## Migrate from 0.9 and earlier 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. 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.

View 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]);
}
}

View File

@ -21,7 +21,7 @@ class CURLHelper
/** /**
* Returns CURL Default Options * Returns CURL Default Options
* *
* @return array * @return array
*/ */
public static function getOptions() public static function getOptions()
@ -34,17 +34,17 @@ class CURLHelper
CURLOPT_CAINFO => Yii::getAlias('@humhub/config/cacert.pem') CURLOPT_CAINFO => Yii::getAlias('@humhub/config/cacert.pem')
); );
if (Setting::Get('enabled', 'proxy')) { if (Yii::$app->settings->get('proxy.enabled')) {
$options[CURLOPT_PROXY] = Setting::Get('server', 'proxy'); $options[CURLOPT_PROXY] = Yii::$app->settings->get('proxy.server');
$options[CURLOPT_PROXYPORT] = Setting::Get('port', 'proxy'); $options[CURLOPT_PROXYPORT] = Yii::$app->settings->get('proxy.port');
if (defined('CURLOPT_PROXYUSERNAME')) { if (defined('CURLOPT_PROXYUSERNAME')) {
$options[CURLOPT_PROXYUSERNAME] = Setting::Get('user', 'proxy'); $options[CURLOPT_PROXYUSERNAME] = Yii::$app->settings->get('proxy.user');
} }
if (defined('CURLOPT_PROXYPASSWORD')) { if (defined('CURLOPT_PROXYPASSWORD')) {
$options[CURLOPT_PROXYPASSWORD] = Setting::Get('password', 'proxy'); $options[CURLOPT_PROXYPASSWORD] = Yii::$app->settings->get('proxy.password');
} }
if (defined('CURLOPT_NOPROXY')) { if (defined('CURLOPT_NOPROXY')) {
$options[CURLOPT_NOPROXY] = Setting::Get('noproxy', 'proxy'); $options[CURLOPT_NOPROXY] = Yii::$app->settings->get('proxy.noproxy');
} }
} }

View File

@ -10,7 +10,7 @@ namespace humhub\libs;
use Yii; use Yii;
use yii\helpers\ArrayHelper; use yii\helpers\ArrayHelper;
use humhub\components\Theme; use humhub\libs\ThemeHelper;
use humhub\models\Setting; use humhub\models\Setting;
/** /**
@ -23,7 +23,7 @@ class DynamicConfig extends \yii\base\Object
/** /**
* Add an array to the dynamic configuration * Add an array to the dynamic configuration
* *
* @param array $new * @param array $new
*/ */
public static function merge($new) public static function merge($new)
@ -32,54 +32,9 @@ class DynamicConfig extends \yii\base\Object
self::save($config); 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 * Returns the dynamic configuration
* *
* @return array * @return array
*/ */
public static function load() public static function load()
@ -103,7 +58,7 @@ class DynamicConfig extends \yii\base\Object
/** /**
* Sets a new dynamic configuration * Sets a new dynamic configuration
* *
* @param array $config * @param array $config
*/ */
public static function save($config) public static function save($config)
@ -135,17 +90,17 @@ class DynamicConfig extends \yii\base\Object
$config = self::load(); $config = self::load();
// Add Application Name to Configuration // Add Application Name to Configuration
$config['name'] = Setting::Get('name'); $config['name'] = Yii::$app->settings->get('name');
// Add Default language // Add Default language
$defaultLanguage = Setting::Get('defaultLanguage'); $defaultLanguage = Yii::$app->settings->get('defaultLanguage');
if ($defaultLanguage !== null && $defaultLanguage != "") { if ($defaultLanguage !== null && $defaultLanguage != "") {
$config['language'] = Setting::Get('defaultLanguage'); $config['language'] = Yii::$app->settings->get('defaultLanguage');
} else { } else {
$config['language'] = Yii::$app->language; $config['language'] = Yii::$app->language;
} }
$timeZone = Setting::Get('timeZone'); $timeZone = Yii::$app->settings->get('timeZone');
if ($timeZone != "") { if ($timeZone != "") {
$config['timeZone'] = $timeZone; $config['timeZone'] = $timeZone;
$config['components']['formatter']['defaultTimeZone'] = $timeZone; $config['components']['formatter']['defaultTimeZone'] = $timeZone;
@ -154,66 +109,55 @@ class DynamicConfig extends \yii\base\Object
} }
// Add Caching // 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'])) { if (in_array($cacheClass, ['yii\caching\DummyCache', 'yii\caching\ApcCache', 'yii\caching\FileCache'])) {
$config['components']['cache'] = [ $config['components']['cache'] = [
'class' => $cacheClass, 'class' => $cacheClass,
'keyPrefix' => Yii::$app->id 'keyPrefix' => Yii::$app->id
]; ];
// Prefix APC Cache Keys
//if ($cacheClass == 'yii\caching\ApcCache') {
// $config['components']['cache'] = [
// 'keyPrefix' => Yii::$app->id
// ];
//}
} }
// Add User settings // Add User settings
$config['components']['user'] = array(); $config['components']['user'] = array();
if (Setting::Get('defaultUserIdleTimeoutSec', 'authentication_internal')) { if (Yii::$app->getModule('user')->settings->get('auth.defaultUserIdleTimeoutSec')) {
$config['components']['user']['authTimeout'] = Setting::Get('defaultUserIdleTimeoutSec', 'authentication_internal'); $config['components']['user']['authTimeout'] = Yii::$app->getModule('user')->settings->get('auth.defaultUserIdleTimeoutSec');
} }
// Install Mail Component // Install Mail Component
$mail = []; $mail = [];
$mail['transport'] = array(); $mail['transport'] = array();
if (Setting::Get('transportType', 'mailing') == 'smtp') { if (Yii::$app->settings->get('mailer.transportType') == 'smtp') {
$mail['transport']['class'] = 'Swift_SmtpTransport'; $mail['transport']['class'] = 'Swift_SmtpTransport';
if (Setting::Get('hostname', 'mailing')) if (Yii::$app->settings->get('mailer.hostname'))
$mail['transport']['host'] = Setting::Get('hostname', 'mailing'); $mail['transport']['host'] = Yii::$app->settings->get('mailer.hostname');
if (Setting::Get('username', 'mailing')) if (Yii::$app->settings->get('mailer.username'))
$mail['transport']['username'] = Setting::Get('username', 'mailing'); $mail['transport']['username'] = Yii::$app->settings->get('mailer.username');
if (Setting::Get('password', 'mailing')) if (Yii::$app->settings->get('mailer.password'))
$mail['transport']['password'] = Setting::Get('password', 'mailing'); $mail['transport']['password'] = Yii::$app->settings->get('mailer.password');
if (Setting::Get('encryption', 'mailing')) if (Yii::$app->settings->get('mailer.encryption'))
$mail['transport']['encryption'] = Setting::Get('encryption', 'mailing'); $mail['transport']['encryption'] = Yii::$app->settings->get('mailer.encryption');
if (Setting::Get('port', 'mailing')) if (Yii::$app->settings->get('mailer.port'))
$mail['transport']['port'] = Setting::Get('port', 'mailing'); $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']['allow_self_signed'] = true;
$mail['transport']['ssl']['verify_peer'] = false; $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'; $mail['transport']['class'] = 'Swift_MailTransport';
} else { } else {
$mail['useFileTransport'] = true; $mail['useFileTransport'] = true;
} }
$config['components']['mailer'] = $mail; $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(); $config['params']['config_created_at'] = time();
foreach (Setting::find()->all() as $setting) {
self::setSettingValue($config['params'], $setting);
}
self::save($config); self::save($config);
} }

View File

@ -513,289 +513,9 @@ class iso3166Codes
"ZW" => "263" "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) 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) public static function phoneCode($code)
@ -803,11 +523,6 @@ class iso3166Codes
return (isset(static::$phoneCodes[strtoupper($code)])) ? static::$phoneCodes[strtoupper($code)] : 'N/A'; 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) public static function isValid($code)
{ {
return isset(static::$countries[strtoupper($code)]); return isset(static::$countries[strtoupper($code)]);

View File

@ -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;
}
}

View File

@ -1,11 +1,21 @@
<?php <?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\libs; namespace humhub\libs;
use Yii; use Yii;
use yii\web\UploadedFile; use yii\web\UploadedFile;
use yii\helpers\Url; use yii\helpers\Url;
use humhub\modules\file\libs\ImageConverter;
/**
* LogoImage
*/
class LogoImage class LogoImage
{ {
@ -19,11 +29,6 @@ class LogoImage
*/ */
protected $folder_images = "logo_image"; protected $folder_images = "logo_image";
public function __construct()
{
}
/** /**
* Returns the URl of Logo Image * Returns the URl of Logo Image
* *

View File

@ -1,26 +1,14 @@
<?php <?php
/** /**
* HumHub * @link https://www.humhub.org/
* Copyright © 2014 The HumHub Project * @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* * @license https://www.humhub.com/licences
* 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; namespace humhub\libs;
use humhub\libs\ImageConverter; use humhub\modules\file\libs\ImageConverter;
/** /**
* ProfileBannerImage is responsible for the profile banner images. * ProfileBannerImage is responsible for the profile banner images.
@ -32,7 +20,6 @@ use humhub\libs\ImageConverter;
* "" = Resized profile image * "" = Resized profile image
* "_org" = Orginal uploaded file * "_org" = Orginal uploaded file
* *
* @package humhub.modules_core.file
* @since 0.5 * @since 0.5
* @author Luke * @author Luke
*/ */

View File

@ -1,28 +1,16 @@
<?php <?php
/** /**
* HumHub * @link https://www.humhub.org/
* Copyright © 2014 The HumHub Project * @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* * @license https://www.humhub.com/licences
* 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; namespace humhub\libs;
use Yii; use Yii;
use yii\helpers\Url; use yii\helpers\Url;
use humhub\libs\ImageConverter; use humhub\modules\file\libs\ImageConverter;
/** /**
* ProfileImage is responsible for all profile images. * ProfileImage is responsible for all profile images.
@ -34,7 +22,6 @@ use humhub\libs\ImageConverter;
* "" = Resized profile image * "" = Resized profile image
* "_org" = Orginal uploaded file * "_org" = Orginal uploaded file
* *
* @package humhub.modules_core.file
* @since 0.5 * @since 0.5
* @author Luke * @author Luke
*/ */

View File

@ -85,7 +85,7 @@ class SelfTest
$icuVersion = (defined('INTL_ICU_VERSION')) ? INTL_ICU_VERSION : 0; $icuVersion = (defined('INTL_ICU_VERSION')) ? INTL_ICU_VERSION : 0;
$icuMinVersion = '4.8.1'; $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, '>=')) { if (version_compare($icuVersion, $icuMinVersion, '>=')) {
$checks[] = array( $checks[] = array(
'title' => Yii::t('base', $title), 'title' => Yii::t('base', $title),
@ -100,7 +100,7 @@ class SelfTest
} }
$icuDataVersion = (defined('INTL_ICU_DATA_VERSION')) ? INTL_ICU_DATA_VERSION : 0; $icuDataVersion = (defined('INTL_ICU_DATA_VERSION')) ? INTL_ICU_DATA_VERSION : 0;
$icuMinDataVersion = '4.8.1'; $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, '>=')) { if (version_compare($icuDataVersion, $icuMinDataVersion, '>=')) {
$checks[] = array( $checks[] = array(
'title' => Yii::t('base', $title), 'title' => Yii::t('base', $title),

View 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,
]
]
]
]
];
}
}

View 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';
}
}

View File

@ -1,56 +1,37 @@
<?php <?php
/** return array (
* Message translations. '<strong>Latest</strong> updates' => '<strong>Zagueras</strong> actividatz',
* 'Account settings' => 'Achustes d\'a cuenta',
* This file is automatically generated by 'yii message' command. 'Administration' => 'Administración',
* It contains the localizable messages extracted from source code. 'Allow' => '',
* You may modify this file by translating the extracted messages. 'Back' => '',
* 'Back to dashboard' => 'Tornar a Encieto',
* Each array element represents the translation (value) of a message (key). 'Choose language:' => '',
* If the value is empty, the message is considered as not translated. 'Collapse' => 'Zarrar',
* Messages that no longer need translation will have their translations 'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '',
* enclosed between a pair of '@@' marks. 'Could not determine content container!' => '',
* 'Could not find content of addon!' => '',
* Message string can be used with plural forms format. Check i18n section 'Default' => '',
* of the guide for details. 'Deny' => '',
* 'Error' => 'Error',
* NOTE: this file must be saved in UTF-8 encoding. 'Expand' => 'Esbandir',
*/ 'It looks like you may have taken the wrong turn.' => 'Pareixe que has tomau o camín incorrecto.',
return [ 'Language' => '',
'Allow' => '', 'Latest news' => 'Zagueras noticias',
'Back' => '', 'Login' => '',
'Choose language:' => '', 'Logout' => 'Zarrar sesión',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '', 'Menu' => 'Menú',
'Could not determine content container!' => '', 'Module is not on this content container enabled!' => '',
'Could not find content of addon!' => '', 'My profile' => 'O mío perfil',
'Default' => '', 'New profile image' => 'Nueva imachen de perfil',
'Deny' => '', 'Next' => '',
'Language' => '', 'Ok' => '',
'Login' => '', 'Oooops...' => 'Oooops...',
'Module is not on this content container enabled!' => '', 'Please type at least 3 characters' => '',
'Next' => '', 'Save' => 'Uložit',
'Please type at least 3 characters' => '', 'Search' => 'Buscar',
'Save' => '', 'Search for users and spaces' => 'Buscar usuarios y espacios',
'<strong>Latest</strong> updates' => '<strong>Zagueras</strong> actividatz', 'Space not found!' => 'Espacio no trobau!',
'Account settings' => 'Achustes d\'a cuenta', 'User not found!' => 'Usuario no trobau!',
'Administration' => 'Administración', 'Your daily summary' => 'Resumen diario',
'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',
];

View File

@ -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

View File

@ -1,56 +1,37 @@
<?php <?php
/** return array (
* Message translations. '<strong>Latest</strong> updates' => '<strong>آخر</strong> التحديثات',
* 'Account settings' => 'إعدادات الحساب',
* This file is automatically generated by 'yii message' command. 'Administration' => 'الإدارة',
* It contains the localizable messages extracted from source code. 'Allow' => '',
* You may modify this file by translating the extracted messages. 'Back' => 'عودة',
* 'Back to dashboard' => 'عودة لسطح المكتب',
* Each array element represents the translation (value) of a message (key). 'Choose language:' => 'خيارات اللغه:',
* If the value is empty, the message is considered as not translated. 'Collapse' => 'إغلاق',
* Messages that no longer need translation will have their translations 'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '@Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!@',
* enclosed between a pair of '@@' marks. 'Could not determine content container!' => 'لم يمكن تحديد content container!',
* 'Could not find content of addon!' => 'لم يمكن ايجاد محتويات الإضافة',
* Message string can be used with plural forms format. Check i18n section 'Default' => '',
* of the guide for details. 'Deny' => '',
* 'Error' => 'خطأ',
* NOTE: this file must be saved in UTF-8 encoding. 'Expand' => 'توسعة',
*/ 'It looks like you may have taken the wrong turn.' => 'يبدو انك أتيت للصفحة الخطأ',
return [ 'Language' => 'اللغة',
'Allow' => '', 'Latest news' => 'آخر الأخبار',
'Default' => '', 'Login' => 'تسجيل الدخول',
'Deny' => '', 'Logout' => 'تسجيل الخروج',
'Next' => '', 'Menu' => 'القائمة',
'Please type at least 3 characters' => '', 'Module is not on this content container enabled!' => 'الموديل ليس متاحاً في هذه الخانة',
'Save' => '', 'My profile' => 'صفحتي الشخصية',
'<strong>Latest</strong> updates' => '<strong>آخر</strong> التحديثات', 'New profile image' => 'صورة شخصية جديدة',
'Account settings' => 'إعدادات الحساب', 'Next' => '',
'Administration' => 'الإدارة', 'Ok' => '',
'Back' => 'عودة', 'Oooops...' => 'يالهوي...',
'Back to dashboard' => 'عودة لسطح المكتب', 'Please type at least 3 characters' => '',
'Choose language:' => 'خيارات اللغه:', 'Save' => 'حفظ',
'Collapse' => 'إغلاق', 'Search' => 'بحث',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '@Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!@', 'Search for users and spaces' => 'البحث عن مستخدمين و باحات',
'Could not determine content container!' => 'لم يمكن تحديد content container!', 'Space not found!' => 'لم اتمكن من إيجاد الباحة!',
'Could not find content of addon!' => 'لم يمكن ايجاد محتويات الإضافة', 'User not found!' => 'لم يتم إيجاد العضو',
'Error' => 'خطأ', 'Your daily summary' => 'المختصر اليومي',
'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' => 'المختصر اليومي',
];

View File

@ -1,4 +0,0 @@
<?php
return array (
'Global {global} array cleaned using {method} method.' => '@Global {global} array cleaned using {method} method.@',
);

View File

@ -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":["Преводи"]}

View File

@ -1,56 +1,37 @@
<?php <?php
/** return array (
* Message translations. '<strong>Latest</strong> updates' => '<strong>Последни</strong> ъпдейти',
* 'Account settings' => 'Настройки на акаунта',
* This file is automatically generated by 'yii message' command. 'Administration' => 'Администрация',
* It contains the localizable messages extracted from source code. 'Allow' => '',
* You may modify this file by translating the extracted messages. 'Back' => 'Назад',
* 'Back to dashboard' => 'Върни се в работното място',
* Each array element represents the translation (value) of a message (key). 'Choose language:' => 'Избери език:',
* If the value is empty, the message is considered as not translated. 'Collapse' => 'Свий',
* Messages that no longer need translation will have their translations 'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '',
* enclosed between a pair of '@@' marks. 'Could not determine content container!' => '',
* 'Could not find content of addon!' => '',
* Message string can be used with plural forms format. Check i18n section 'Default' => '',
* of the guide for details. 'Deny' => '',
* 'Error' => 'Грешка',
* NOTE: this file must be saved in UTF-8 encoding. 'Expand' => 'Разшири',
*/ 'It looks like you may have taken the wrong turn.' => '',
return [ 'Language' => 'Език',
'Allow' => '', 'Latest news' => 'Последни новини',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '', 'Login' => 'Вход',
'Could not determine content container!' => '', 'Logout' => 'Изход',
'Could not find content of addon!' => '', 'Menu' => 'Меню',
'Default' => '', 'Module is not on this content container enabled!' => '',
'Deny' => '', 'My profile' => 'Моят Профил',
'Insufficent permissions to create content!' => '', 'New profile image' => 'Нова профилна картинка',
'It looks like you may have taken the wrong turn.' => '', 'Next' => '',
'Module is not on this content container enabled!' => '', 'Ok' => '',
'Next' => '', 'Oooops...' => 'Опаля...',
'Please type at least 3 characters' => '', 'Please type at least 3 characters' => '',
'Save' => '', 'Save' => 'Запази',
'User Approvals' => '', 'Search' => 'Търси',
'You cannot create public visible content!' => '', 'Search for users and spaces' => 'Търси хора и зони',
'Your daily summary' => '', 'Space not found!' => 'Зоната не е открита!',
'<strong>Latest</strong> updates' => '<strong>Последни</strong> ъпдейти', 'User not found!' => 'Потребителя не е намерен!',
'Account settings' => 'Настройки на акаунта', 'Your daily summary' => '',
'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!' => 'Потребителя не е намерен!',
];

View File

@ -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

View File

@ -1,56 +1,37 @@
<?php <?php
/** return array (
* Message translations. '<strong>Latest</strong> updates' => '<strong>Últimes</strong> actualitzacions',
* 'Account settings' => 'Configuració del compte',
* This file is automatically generated by 'yii message' command. 'Administration' => 'Administració',
* It contains the localizable messages extracted from source code. 'Allow' => '',
* You may modify this file by translating the extracted messages. 'Back' => 'Enrere',
* 'Back to dashboard' => 'Torna a la portada',
* Each array element represents the translation (value) of a message (key). 'Choose language:' => 'Escull un idioma:',
* If the value is empty, the message is considered as not translated. 'Collapse' => 'Redueix',
* Messages that no longer need translation will have their translations 'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '',
* enclosed between a pair of '@@' marks. 'Could not determine content container!' => '',
* 'Could not find content of addon!' => '',
* Message string can be used with plural forms format. Check i18n section 'Default' => '',
* of the guide for details. 'Deny' => '',
* 'Error' => 'Error',
* NOTE: this file must be saved in UTF-8 encoding. 'Expand' => 'Amplia',
*/ 'It looks like you may have taken the wrong turn.' => '',
return [ 'Language' => 'Llengua',
'Allow' => '', 'Latest news' => 'Últimes notícies',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => '', 'Login' => 'Inici de sessió',
'Could not determine content container!' => '', 'Logout' => 'Sortir',
'Could not find content of addon!' => '', 'Menu' => 'Menú',
'Default' => '', 'Module is not on this content container enabled!' => '',
'Deny' => '', 'My profile' => 'El meu perfil',
'It looks like you may have taken the wrong turn.' => '', 'New profile image' => 'Nova imatge de perfil',
'Module is not on this content container enabled!' => '', 'Next' => 'Següent',
'Next' => '', 'Ok' => 'D\'acord',
'Please type at least 3 characters' => '', 'Oooops...' => 'Oooops...',
'Save' => '', 'Please type at least 3 characters' => '',
'<strong>Latest</strong> updates' => '<strong>Últimes</strong> actualitzacions', 'Save' => 'Desa',
'Account settings' => 'Configuració del compte', 'Search' => 'Cerca',
'Administration' => 'Administració', 'Search for users and spaces' => 'Cerca per membres i espais',
'Back' => 'Enrere', 'Space not found!' => 'Espai no trobat!',
'Back to dashboard' => 'Torna a la portada', 'User not found!' => 'Membre no trobat!',
'Choose language:' => 'Escull un idioma:', 'Your daily summary' => 'El teu resum diari',
'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',
];

View File

@ -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

View File

@ -1,56 +1,37 @@
<?php <?php
/** return array (
* Message translations. '<strong>Latest</strong> updates' => '<strong>Poslední</strong> události',
* 'Account settings' => 'Nastavení účtu',
* This file is automatically generated by 'yii message' command. 'Administration' => 'Administrace',
* It contains the localizable messages extracted from source code. 'Allow' => 'Povolit',
* You may modify this file by translating the extracted messages. 'Back' => 'Zpět',
* 'Back to dashboard' => 'Zpět na nástěnku',
* Each array element represents the translation (value) of a message (key). 'Choose language:' => 'Vyberte jazyk:',
* If the value is empty, the message is considered as not translated. 'Collapse' => 'Sbalit',
* Messages that no longer need translation will have their translations 'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Content Addon musí být buď instancí objektu HActiveRecordContent nebo HActiveRecordContentAddon!',
* enclosed between a pair of '@@' marks. 'Could not determine content container!' => 'Obsah nenalezen!',
* 'Could not find content of addon!' => 'Nebylo možné nalézt obsah dolpňku!',
* Message string can be used with plural forms format. Check i18n section 'Default' => 'Výchozí',
* of the guide for details. 'Deny' => 'Odmítnout',
* 'Error' => 'Chyba',
* NOTE: this file must be saved in UTF-8 encoding. 'Expand' => 'Rozbalit',
*/ 'It looks like you may have taken the wrong turn.' => 'Zdá se, že jste někde špatně odbočili.',
return [ 'Language' => 'Jazyk',
'<strong>Latest</strong> updates' => '<strong>Poslední</strong> události', 'Latest news' => 'Poslední události',
'Account settings' => 'Nastavení účtu', 'Login' => 'Přihlásit se',
'Administration' => 'Administrace', 'Logout' => 'Odhlásit',
'Allow' => 'Povolit', 'Menu' => 'Menu',
'Back' => 'Zpět', 'Module is not on this content container enabled!' => 'Modul nebyl nalezen nebo je vypnut!',
'Back to dashboard' => 'Zpět na nástěnku', 'My profile' => 'Můj profil',
'Choose language:' => 'Vyberte jazyk:', 'New profile image' => 'Nový profilový obrázek',
'Collapse' => 'Sbalit', 'Next' => 'Další',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Content Addon musí být buď instancí objektu HActiveRecordContent nebo HActiveRecordContentAddon!', 'Ok' => 'Ok',
'Could not determine content container!' => 'Obsah nenalezen!', 'Oooops...' => 'Jejda...',
'Could not find content of addon!' => 'Nebylo možné nalézt obsah dolpňku!', 'Please type at least 3 characters' => 'Napište prosím alespoň 3 znaky',
'Default' => 'Výchozí', 'Save' => 'Uložit',
'Deny' => 'Odmítnout', 'Search' => 'Hledat',
'Error' => 'Chyba', 'Search for users and spaces' => 'Hledat mezi uživateli a prostory',
'Expand' => 'Rozbalit', 'Space not found!' => 'Prostor nebyl nalezen!',
'Insufficent permissions to create content!' => 'Nedostatečná práva pro vytvoření obsahu!', 'User not found!' => 'Uživatel nebyl nalezen!',
'It looks like you may have taken the wrong turn.' => 'Zdá se, že jste někde špatně odbočili.', 'Your daily summary' => 'Vaše denní shrnutí',
'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í',
];

View File

@ -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

View File

@ -1,56 +1,37 @@
<?php <?php
/** return array (
* Message translations. '<strong>Latest</strong> updates' => '<strong>Nyeste</ strong> opdateringer',
* 'Account settings' => 'Kontoindstillinger',
* This file is automatically generated by 'yii message' command. 'Administration' => 'Administration',
* It contains the localizable messages extracted from source code. 'Allow' => 'Tillad',
* You may modify this file by translating the extracted messages. 'Back' => 'Tilbage',
* 'Back to dashboard' => 'Tilbage til dashboard',
* Each array element represents the translation (value) of a message (key). 'Choose language:' => 'Vælg sprog:',
* If the value is empty, the message is considered as not translated. 'Collapse' => 'Kollaps',
* Messages that no longer need translation will have their translations 'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Indholdskilde addon skal være del en af HActiveRecordContent eller HActiveRecordContentAddon!',
* enclosed between a pair of '@@' marks. 'Could not determine content container!' => 'Kunne ikke fastslå indholdscontainer!',
* 'Could not find content of addon!' => 'Kunne ikke finde addonindhold!',
* Message string can be used with plural forms format. Check i18n section 'Default' => 'Standard',
* of the guide for details. 'Deny' => 'Afslå',
* 'Error' => 'Fejl',
* NOTE: this file must be saved in UTF-8 encoding. 'Expand' => 'Udvid',
*/ 'It looks like you may have taken the wrong turn.' => 'Det ser ud som du måske har taget den forkerte drejning.',
return [ 'Language' => 'Sprog',
'<strong>Latest</strong> updates' => '<strong>Nyeste</ strong> opdateringer', 'Latest news' => 'Sidste nyt',
'Account settings' => 'Kontoindstillinger', 'Login' => 'Log ind',
'Administration' => 'Administration', 'Logout' => 'Log ud',
'Allow' => 'Tillad', 'Menu' => 'Menu',
'Back' => 'Tilbage', 'Module is not on this content container enabled!' => 'Modulet er ikke aktiveret i denne indholdscontainer!',
'Back to dashboard' => 'Tilbage til dashboard', 'My profile' => 'Min profil',
'Choose language:' => 'Vælg sprog:', 'New profile image' => 'Nyt profilbillede',
'Collapse' => 'Kollaps', 'Next' => 'Næste',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Indholdskilde addon skal være del en af HActiveRecordContent eller HActiveRecordContentAddon!', 'Ok' => 'Ok',
'Could not determine content container!' => 'Kunne ikke fastslå indholdscontainer!', 'Oooops...' => 'Hovsa...',
'Could not find content of addon!' => 'Kunne ikke finde addonindhold!', 'Please type at least 3 characters' => 'Venligst indtast mindst 3 tegn',
'Default' => 'Standard', 'Save' => 'Gem',
'Deny' => 'Afslå', 'Search' => 'Søg',
'Error' => 'Fejl', 'Search for users and spaces' => 'Søg efter brugere eller sider',
'Expand' => 'Udvid', 'Space not found!' => 'Side ikke fundet!',
'Insufficent permissions to create content!' => 'Utilstrækkelige tilladelser til at skabe indhold!', 'User not found!' => 'Bruger ikke fundet!',
'It looks like you may have taken the wrong turn.' => 'Det ser ud som du måske har taget den forkerte drejning.', 'Your daily summary' => 'Dit daglige resumé',
'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é',
];

View File

@ -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

View File

@ -1,56 +1,37 @@
<?php <?php
/** return array (
* Message translations. '<strong>Latest</strong> updates' => '<strong>Letzte</strong> Aktualisierungen',
* 'Account settings' => 'Kontoeinstellungen',
* This file is automatically generated by 'yii message' command. 'Administration' => 'Administration',
* It contains the localizable messages extracted from source code. 'Allow' => 'Erlauben',
* You may modify this file by translating the extracted messages. 'Back' => 'Zurück',
* 'Back to dashboard' => 'Zurück zur Übersicht',
* Each array element represents the translation (value) of a message (key). 'Choose language:' => 'Sprache wählen:',
* If the value is empty, the message is considered as not translated. 'Collapse' => 'Einklappen',
* Messages that no longer need translation will have their translations 'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Die Quelle des Addons muss eine Instanz von HActiveRecordContent oder HActiveRecordContentAddon sein!',
* enclosed between a pair of '@@' marks. 'Could not determine content container!' => 'Kann Content Container nicht finden.',
* 'Could not find content of addon!' => 'Der Inhalt des Addons konnte nicht gefunden werden!',
* Message string can be used with plural forms format. Check i18n section 'Default' => 'Standard',
* of the guide for details. 'Deny' => 'Ablehnen',
* 'Error' => 'Fehler',
* NOTE: this file must be saved in UTF-8 encoding. 'Expand' => 'Erweitern',
*/ 'It looks like you may have taken the wrong turn.' => 'Du hast womöglich den falschen Weg eingeschlagen.',
return [ 'Language' => 'Sprache',
'<strong>Latest</strong> updates' => '<strong>Letzte</strong> Aktualisierungen', 'Latest news' => 'Neuigkeiten',
'Account settings' => 'Kontoeinstellungen', 'Login' => 'Anmelden',
'Administration' => 'Administration', 'Logout' => 'Ausloggen',
'Allow' => 'Erlauben', 'Menu' => 'Menü',
'Back' => 'Zurück', 'Module is not on this content container enabled!' => 'Dieses Modul ist in diesem Content Container nicht aktiviert!',
'Back to dashboard' => 'Zurück zur Übersicht', 'My profile' => 'Mein Profil',
'Choose language:' => 'Sprache wählen:', 'New profile image' => 'Neues Profilbild',
'Collapse' => 'Einklappen', 'Next' => 'Nächster',
'Content Addon source must be instance of HActiveRecordContent or HActiveRecordContentAddon!' => 'Die Quelle des Addons muss eine Instanz von HActiveRecordContent oder HActiveRecordContentAddon sein!', 'Ok' => 'Ok',
'Could not determine content container!' => 'Kann Content Container nicht finden.', 'Oooops...' => 'Uuuups...',
'Could not find content of addon!' => 'Der Inhalt des Addons konnte nicht gefunden werden!', 'Please type at least 3 characters' => 'Bitte wengistens 3 Zeichen eingeben',
'Default' => 'Standard', 'Save' => 'Speichern',
'Deny' => 'Ablehnen', 'Search' => 'Suchen',
'Error' => 'Fehler', 'Search for users and spaces' => 'Suche nach Benutzern und Spaces',
'Expand' => 'Erweitern', 'Space not found!' => 'Space nicht gefunden!',
'Insufficent permissions to create content!' => 'Unzureichende Berechtigungen um Inhalte zu erstellen!', 'User not found!' => 'Benutzer nicht gefunden!',
'It looks like you may have taken the wrong turn.' => 'Du hast womöglich den falschen Weg eingeschlagen.', 'Your daily summary' => 'Deine tägliche Übersicht',
'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',
];

View File

@ -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.',
);

View File

@ -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