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

This commit is contained in:
Lucas Bartholemy 2016-05-19 19:41:43 +02:00
commit d8fc0d251f
34 changed files with 428 additions and 652 deletions

View File

@ -1,330 +0,0 @@
<?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;
/**
* 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 (Yii::$app->getModule('file')->settings->get('imageMagickPath')) {
$convertCommand = Yii::$app->getModule('file')->settings->get('imageMagickPath');
$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 (Yii::$app->getModule('file')->settings->get('imageMagickPath')) {
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 = Yii::$app->getModule('file')->settings->get('imageMagickPath');
$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
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\libs;
use Yii;
use yii\web\UploadedFile;
use yii\helpers\Url;
use humhub\modules\file\libs\ImageConverter;
/**
* LogoImage
*/
class LogoImage
{
@ -19,11 +29,6 @@ class LogoImage
*/
protected $folder_images = "logo_image";
public function __construct()
{
}
/**
* Returns the URl of Logo Image
*

View File

@ -1,26 +1,14 @@
<?php
/**
* HumHub
* Copyright © 2014 The HumHub Project
*
* The texts of the GNU Affero General Public License with an additional
* permission and of our proprietary license can be found at and
* in the LICENSE file you have received along with this program.
*
* According to our dual licensing model, this program can be used either
* under the terms of the GNU Affero General Public License, version 3,
* or under a proprietary license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* @link https://www.humhub.org/
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\libs;
use humhub\libs\ImageConverter;
use humhub\modules\file\libs\ImageConverter;
/**
* ProfileBannerImage is responsible for the profile banner images.
@ -32,7 +20,6 @@ use humhub\libs\ImageConverter;
* "" = Resized profile image
* "_org" = Orginal uploaded file
*
* @package humhub.modules_core.file
* @since 0.5
* @author Luke
*/

View File

@ -1,28 +1,16 @@
<?php
/**
* HumHub
* Copyright © 2014 The HumHub Project
*
* The texts of the GNU Affero General Public License with an additional
* permission and of our proprietary license can be found at and
* in the LICENSE file you have received along with this program.
*
* According to our dual licensing model, this program can be used either
* under the terms of the GNU Affero General Public License, version 3,
* or under a proprietary license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
* @link https://www.humhub.org/
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\libs;
use Yii;
use yii\helpers\Url;
use humhub\libs\ImageConverter;
use humhub\modules\file\libs\ImageConverter;
/**
* ProfileImage is responsible for all profile images.
@ -34,7 +22,6 @@ use humhub\libs\ImageConverter;
* "" = Resized profile image
* "_org" = Orginal uploaded file
*
* @package humhub.modules_core.file
* @since 0.5
* @author Luke
*/

View File

@ -4,6 +4,7 @@ namespace humhub\modules\admin\models\forms;
use Yii;
use humhub\modules\space\models\Space;
use humhub\modules\content\components\actions\Stream;
use humhub\libs\DynamicConfig;
/**
@ -20,6 +21,7 @@ class BasicSettingsForm extends \yii\base\Model
public $defaultSpaceGuid;
public $tour;
public $timeZone;
public $defaultStreamSort;
public $dashboardShowProfilePostForm;
public $enableFriendshipModule;
@ -43,6 +45,8 @@ class BasicSettingsForm extends \yii\base\Model
foreach (\humhub\modules\space\models\Space::findAll(['auto_add_new_members' => 1]) as $defaultSpace) {
$this->defaultSpaceGuid .= $defaultSpace->guid . ",";
}
$this->defaultStreamSort = Yii::$app->getModule('content')->settings->get('stream.defaultSort');
}
/**
@ -50,14 +54,15 @@ class BasicSettingsForm extends \yii\base\Model
*/
public function rules()
{
return array(
array(['name', 'baseUrl'], 'required'),
array('name', 'string', 'max' => 150),
array('defaultLanguage', 'in', 'range' => array_keys(Yii::$app->i18n->getAllowedLanguages())),
array('timeZone', 'in', 'range' => \DateTimeZone::listIdentifiers()),
array('defaultSpaceGuid', 'checkSpaceGuid'),
array(['tour', 'dashboardShowProfilePostForm', 'enableFriendshipModule'], 'in', 'range' => array(0, 1))
);
return [
[['name', 'baseUrl'], 'required'],
['name', 'string', 'max' => 150],
['defaultLanguage', 'in', 'range' => array_keys(Yii::$app->i18n->getAllowedLanguages())],
['timeZone', 'in', 'range' => \DateTimeZone::listIdentifiers()],
['defaultSpaceGuid', 'checkSpaceGuid'],
[['tour', 'dashboardShowProfilePostForm', 'enableFriendshipModule'], 'in', 'range' => [0, 1]],
[['defaultStreamSort'], 'in', 'range' => array_keys($this->getDefaultStreamSortOptions())]
];
}
/**
@ -74,6 +79,7 @@ class BasicSettingsForm extends \yii\base\Model
'tour' => Yii::t('AdminModule.forms_BasicSettingsForm', 'Show introduction tour for new users'),
'dashboardShowProfilePostForm' => Yii::t('AdminModule.forms_BasicSettingsForm', 'Show user profile post form on dashboard'),
'enableFriendshipModule' => Yii::t('AdminModule.forms_BasicSettingsForm', 'Enable user friendship system'),
'defaultStreamSort' => Yii::t('AdminModule.forms_BasicSettingsForm', 'Default stream content order')
);
}
@ -114,6 +120,7 @@ class BasicSettingsForm extends \yii\base\Model
Yii::$app->getModule('dashboard')->settings->set('showProfilePostForm', $this->dashboardShowProfilePostForm);
Yii::$app->getModule('tour')->settings->set('enable', $this->tour);
Yii::$app->getModule('friendship')->settings->set('enable', $this->enableFriendshipModule);
Yii::$app->getModule('content')->settings->set('stream.defaultSort', $this->defaultStreamSort);
$spaceGuids = explode(",", $this->defaultSpaceGuid);
@ -138,4 +145,17 @@ class BasicSettingsForm extends \yii\base\Model
return true;
}
/**
* Returns available options for defaultStreamSort attribute
*
* @return array
*/
public function getDefaultStreamSortOptions()
{
return [
Stream::SORT_CREATED_AT => Yii::t('AdminModule.forms_BasicSettingsForm', 'Sort by creation date'),
Stream::SORT_UPDATED_AT => Yii::t('AdminModule.forms_BasicSettingsForm', 'Sort by update date'),
];
}
}

View File

@ -25,8 +25,8 @@ use yii\widgets\ActiveForm;
<?php endif; ?>
<?php echo $form->field($model, 'timeZone')->dropdownList(\humhub\libs\TimezoneHelper::generateList()); ?>
<?php echo $form->field($model, 'defaultSpaceGuid')->textInput(['id' => 'space_select']); ?>
<?php echo $form->field($model, 'defaultStreamSort')->dropdownList($model->getDefaultStreamSortOptions()); ?>
<?php
echo \humhub\modules\space\widgets\Picker::widget([

View File

@ -0,0 +1,30 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\modules\admin\widgets;
use Yii;
/**
* TrackingWidget adds statistic tracking code to all layouts
*
* @since 1.1
* @author Luke
*/
class TrackingWidget extends \humhub\components\Widget
{
/**
* @inheritdoc
*/
public function run()
{
return Yii::$app->settings->get('trackingHtmlCode');
}
}

View File

@ -16,10 +16,9 @@ function Stream(baseElement) {
this.baseDiv = baseElement;
this.debug = true;
this.filters = "";
this.sorting = "c";
this.sorting = defaultStreamSort;
this.limit = 4;
/**
* Return parseHtml result and delete dublicated entries from container
* @param {object} json JSON object
@ -112,15 +111,15 @@ function Stream(baseElement) {
url = streamUrl;
url = url.replace('-filter-', '');
url = url.replace('-sort-', '');
url = url.replace('-from-', parseInt(wallEntryId)+1);
url = url.replace('-from-', parseInt(wallEntryId) + 1);
url = url.replace('-limit-', 1);
// Load Entry
jQuery.getJSON(url, function (json) {
streamDiv = $(me.baseDiv).find(".s2_singleContent");
//$(json.output).appendTo(streamDiv).fadeIn('fast');
$(streamDiv).append(parseEntriesHtml(json,streamDiv ));
$(streamDiv).append(parseEntriesHtml(json, streamDiv));
me.lastEntryLoaded = true;
me.loadedEntryCount += json.counter;
@ -184,15 +183,20 @@ function Stream(baseElement) {
streamDiv = $(me.baseDiv).find(".s2_streamContent");
//$(json.output).appendTo(streamDiv).fadeIn('fast');
$(streamDiv).append(parseEntriesHtml(json,streamDiv ));
$(streamDiv).append(parseEntriesHtml(json, streamDiv));
me.lastLoadedEntryId = json.lastEntryId;
me.onNewEntries();
me.loadMore();
installAutoLoader();
});
$('.wallSorting').children("i").removeClass('fa-check-square-o');
$('.wallSorting').children("i").removeClass('fa-square-o');
$('.wallSorting').children("i").addClass('fa-square-o');
$('#sorting_' + this.sorting).children("i").removeClass('fa-square-o');
$('#sorting_' + this.sorting).children("i").addClass('fa-check-square-o');
}
@ -229,7 +233,7 @@ function Stream(baseElement) {
var url = streamUrl;
url = url.replace('-filter-', '');
url = url.replace('-sort-', '');
url = url.replace('-from-', parseInt(wallEntryId)+1);
url = url.replace('-from-', parseInt(wallEntryId) + 1);
url = url.replace('-limit-', 1);
jQuery.getJSON(url, function (json) {
@ -237,16 +241,16 @@ function Stream(baseElement) {
var $streamDiv = $(me.baseDiv).find(".s2_streamContent");
var $newEntryHtml = $(parseEntriesHtml(json)).hide();
var $firstUnstickedEntry = $streamDiv.find('.wall-entry:not(.sticked-entry)').first();
if($firstUnstickedEntry.length) {
if ($firstUnstickedEntry.length) {
$firstUnstickedEntry.before($newEntryHtml);
$newEntryHtml.fadeIn('fast');
} else {
$newEntryHtml.prependTo($streamDiv).fadeIn('fast');
}
me.onNewEntries();
// In case of first post / hide message
@ -291,7 +295,7 @@ function Stream(baseElement) {
streamDiv = $(me.baseDiv).find(".s2_streamContent");
//$(json.output).appendTo(streamDiv).fadeIn('fast');
$(streamDiv).append(parseEntriesHtml(json,streamDiv ));
$(streamDiv).append(parseEntriesHtml(json, streamDiv));
me.lastLoadedEntryId = json.lastEntryId;
me.onNewEntries();
@ -365,7 +369,6 @@ function Stream(baseElement) {
me.showStream();
});
}
/**

View File

@ -33,6 +33,11 @@ use humhub\modules\content\components\ContentAddonActiveRecord;
class ContentAddonActiveRecord extends ActiveRecord implements \humhub\modules\content\interfaces\ContentTitlePreview
{
/**
* @var boolean also update underlying contents last update stream sorting
*/
protected $updateContentStreamSort = true;
/**
* Content object which this addon belongs to
*
@ -190,6 +195,10 @@ class ContentAddonActiveRecord extends ActiveRecord implements \humhub\modules\c
// Auto follow the content which this addon belongs to
$this->content->getPolymorphicRelation()->follow($this->created_by);
if ($this->updateContentStreamSort) {
$this->getSource()->content->updateStreamSortTime();
}
return parent::afterSave($insert, $changedAttributes);
}

View File

@ -71,11 +71,11 @@ class ContentContainerActiveRecord extends ActiveRecord
* Creates url in content container scope.
* E.g. add uguid or sguid parameter to parameters.
*
* @param type $route
* @param type $params
* @param type $ampersand
* @param string $route
* @param array $params
* @param boolean|string $scheme
*/
public function createUrl($route, $params = array(), $ampersand = '&')
public function createUrl($route = null, $params = array(), $scheme = false)
{
return "";
}

View File

@ -103,10 +103,17 @@ class Stream extends \yii\base\Action
if ($from != 0) {
$this->from = (int) $from;
}
$sort = Yii::$app->getRequest()->get('sort', '');
if ($sort != "") {
/**
* Sorting
*/
$sort = Yii::$app->getRequest()->get('sort', Yii::$app->getModule('content')->settings->get('stream.defaultSort'));
if ($sort === static::SORT_CREATED_AT || $sort === static::SORT_UPDATED_AT) {
$this->sort = $sort;
} else {
$this->sort = static::SORT_CREATED_AT;
}
$limit = Yii::$app->getRequest()->get('limit', '');
if ($limit != "" && $limit <= self::MAX_LIMIT) {
$this->limit = $limit;

View File

@ -613,4 +613,15 @@ class Content extends \humhub\components\ActiveRecord
return false;
}
/**
* Updates the wall/stream sorting time of this content for "updated at" sorting
*/
public function updateStreamSortTime()
{
foreach ($this->getWallEntries() as $wallEntry) {
$wallEntry->updated_at = new \yii\db\Expression('NOW()');
$wallEntry->save();
}
}
}

View File

@ -1,112 +0,0 @@
<?php
namespace humhub\modules\content\widgets;
/**
* Wall Stream Widget creates a wall widget.
*
* *** DEPRECATED since 0.11 use StreamWidget instead! ***
*
* @package humhub.modules_core.wall.widgets
* @since 0.5
* @deprecated since version 0.11
*/
class WallStreamWidget extends HWidget
{
/**
* Type of Stream (Wall::TYPE_*)
*
* Can be null if content container is set.
*
* @var string
*/
public $type;
/**
* ContentContainer (e.g. User, Space) which this space belongs to
*
* @var HActiveRecordContentContainer
*/
public $contentContainer;
/**
* Path to Stream Action to use
*
* @var string
*/
public $streamAction = "//wall/wall/stream";
/**
* Number of stream content loaded by request.
*
* Should be at least 4, because its possible to stick at maximum 3 object
* Otherwise sticky system may break the wall
*
* @var int
*/
public $wallObjectStreamLimit = 4;
/**
* Inits the Wall Stream Widget
*/
public function init()
{
if ($this->contentContainer != null) {
$this->type = get_class($this->contentContainer);
}
Yii::app()->clientScript->registerScriptFile(
Yii::app()->assetManager->publish(
Yii::getPathOfAlias('application.modules_core.wall.assets.deprecated') . '/si_streaming.js'
), CClientScript::POS_BEGIN
);
Yii::app()->clientScript->registerScriptFile(
Yii::app()->assetManager->publish(
Yii::getPathOfAlias('application.modules_core.wall.assets') . '/wall.js'
), CClientScript::POS_BEGIN
);
}
/**
* Creates the Wall Widget
*/
public function run()
{
// Save Wall Type
Wall::$currentType = $this->type;
$guid = null;
if ($this->contentContainer != "") {
$guid = $this->contentContainer->guid;
}
// Set some Urls for this wall
$reloadUrl = Yii::app()->createUrl($this->streamAction, array('type' => $this->type, 'guid' => $guid, 'limit' => $this->wallObjectStreamLimit, 'from' => 'lastEntryId', 'filters' => 'filter_placeholder', 'sort' => 'sort_placeholder'));
$startUrl = Yii::app()->createUrl($this->streamAction, array('type' => $this->type, 'guid' => $guid, 'limit' => $this->wallObjectStreamLimit, 'filters' => 'filter_placeholder', 'sort' => 'sort_placeholder'));
$singleEntryUrl = Yii::app()->createUrl($this->streamAction, array('type' => $this->type, 'guid' => $guid, 'limit' => 1, 'from' => 'fromEntryId'));
$view = 'stream_deprecated';
/**
* For backward compatiblity use modules 'stream' view
*/
if (get_class($this) != 'WallStreamWidget') {
$view = 'stream';
}
// Render It
$this->render($view, array(
'type' => $this->type,
'reloadUrl' => $reloadUrl,
'startUrl' => $startUrl,
'singleEntryUrl' => $singleEntryUrl,
));
}
}
?>

View File

@ -17,6 +17,9 @@ $jsLoadWall .= "currentStream = s;\n";
$jsLoadWall .= "mainStream = s;\n";
$jsLoadWall .= "$('#btn-load-more').click(function() { currentStream.loadMore(); })\n";
$this->registerJs($jsLoadWall, View::POS_READY);
$defaultStreamSort = Yii::$app->getModule('content')->settings->get('stream.defaultSort');
$this->registerJsVar('defaultStreamSort', ($defaultStreamSort != '') ? $defaultStreamSort : 'c');
?>
<?php if ($this->context->showFilters) { ?>
@ -38,7 +41,7 @@ $this->registerJs($jsLoadWall, View::POS_READY);
<b class="caret"></b></a>
<ul class="dropdown-menu">
<li><a href="#" class="wallSorting" id="sorting_c"><i
class="fa fa-check-square-o"></i> <?php echo Yii::t('ContentModule.widgets_views_stream', 'Creation time'); ?></a></li>
class="fa fa-square-o"></i> <?php echo Yii::t('ContentModule.widgets_views_stream', 'Creation time'); ?></a></li>
<li><a href="#" class="wallSorting" id="sorting_u"><i
class="fa fa-square-o"></i> <?php echo Yii::t('ContentModule.widgets_views_stream', 'Last update'); ?></a></li>
</ul>

View File

@ -1,12 +1,19 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\modules\dashboard\widgets;
use humhub\widgets\BaseStack;
use humhub\widgets\BaseSidebar;
class Sidebar extends BaseStack
/**
* Sidebar implements the dashboards sidebar
*/
class Sidebar extends BaseSidebar
{
}
?>

View File

@ -1,5 +1,11 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\modules\directory\widgets;
use Yii;

View File

@ -1,20 +1,24 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\modules\directory\widgets;
use humhub\widgets\BaseSidebar;
/**
* DirectorySidebarWidget is a extended class of StackWidgets.
* Sidebar for the directory section
*
* Is used as base for the sidebar in directory sections.
* Modules can attach it´s widget to it.
*
* @package humhub.modules_core.directory.widgets
* @since 0.5
* @author Luke
*/
class Sidebar extends \humhub\widgets\BaseStack
class Sidebar extends BaseSidebar
{
}
?>

View File

@ -31,6 +31,11 @@ use humhub\modules\content\components\ContentAddonActiveRecord;
class Like extends ContentAddonActiveRecord
{
/**
* @inheritdoc
*/
protected $updateContentStreamSort = false;
/**
* @return string the associated database table name
*/

View File

@ -19,6 +19,11 @@ use humhub\modules\content\components\MailUpdateSender;
class Module extends \humhub\components\Module
{
/**
* @var int the seconds the browser checks for new notifications
*/
public $pollClientUpdateInterval = 20;
/**
* Returns all notifications which should be send by e-mail to the given user
* in the given interval
@ -60,7 +65,7 @@ class Module extends \humhub\components\Module
return [];
}
}
$query = Notification::findGrouped()->andWhere(['user_id' => $user->id])->andWhere(['!=', 'seen', 1])->andWhere(['!=', 'emailed', 1]);
foreach ($query->all() as $notification) {
$notifications[] = $notification->getClass();

View File

@ -1,5 +1,11 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\modules\notification\widgets;
use Yii;
@ -8,14 +14,13 @@ use Yii;
* NotificationListWidget shows an stream of notifications for an user at the top menu.
*
* @author andystrobel
* @package humhub.modules_core.notification
* @since 0.5
*/
class Overview extends \yii\base\Widget
{
/**
* Runs the notification widget
* @inheritdoc
*/
public function run()
{
@ -23,7 +28,8 @@ class Overview extends \yii\base\Widget
return;
return $this->render('overview', array(
'update' => \humhub\modules\notification\controllers\ListController::getUpdates()
'update' => \humhub\modules\notification\controllers\ListController::getUpdates(),
'updateInterval' => Yii::$app->getModule('notification')->pollClientUpdateInterval
));
}

View File

@ -155,7 +155,7 @@ use yii\helpers\Url;
/**
* Regulary fetch new notifications
*/
reloadNotificationInterval = 15000;
reloadNotificationInterval = <?= $updateInterval * 1000; ?>;
setInterval(function () {
jQuery.getJSON("<?php echo Url::to(['/notification/list/get-update-json']); ?>", function (json) {
handleJsonUpdate(json);

View File

@ -8,7 +8,6 @@
namespace humhub\modules\search\engine;
use Yii;
use humhub\modules\search\interfaces\Searchable;
use humhub\modules\content\models\Content;
@ -33,6 +32,11 @@ abstract class Search extends \yii\base\Component
const DOCUMENT_VISIBILITY_PUBLIC = 'public';
const DOCUMENT_VISIBILITY_PRIVATE = 'private';
/**
* @var int the minimum length of a search token
*/
public $minQueryTokenLength = 2;
/**
* Retrieves results from search
*
@ -51,50 +55,33 @@ abstract class Search extends \yii\base\Component
* @param array $options
* @return SearchResultSet
*/
public function find($query, Array $options)
{
}
abstract public function find($query, Array $options);
/**
* Stores an object in search.
* Stores an object in search index.
*
* @param Searchable $object
*/
public function add(Searchable $object)
{
}
abstract public function add(Searchable $object);
/**
* Updates an object in search index.
*
* @param Searchable $object
*/
public function update(Searchable $object)
{
}
abstract public function update(Searchable $object);
/**
* Deletes an object in search.
* Deletes an object from search.
*
* @param Searchable $object
*/
public function delete(Searchable $object)
{
}
abstract public function delete(Searchable $object);
/**
* Deletes all objects from search index.
*
* @param Searchable $object
*/
public function flush()
{
}
abstract public function flush();
/**
* Rebuilds search index
@ -107,11 +94,12 @@ abstract class Search extends \yii\base\Component
}
/**
* Optimizes the search index
* Optimizes the search index.
* Default implementation does nothing, may be overidden by child classes.
*/
public function optimize()
{
}
protected function getMetaInfoArray(Searchable $obj)

View File

@ -25,6 +25,9 @@ use humhub\modules\space\models\Space;
class ZendLuceneSearch extends Search
{
/**
* @var \ZendSearch\Lucene\SearchIndexInterface the lucence index
*/
public $index = null;
public function add(Searchable $obj)
@ -108,10 +111,15 @@ class ZendLuceneSearch extends Search
$index = $this->getIndex();
$keyword = str_replace(array('*', '?', '_', '$'), ' ', mb_strtolower($keyword, 'utf-8'));
$query = $this->buildQuery($keyword, $options);
if ($query === null) {
return new SearchResultSet();
}
if (!isset($options['sortField']) || $options['sortField'] == "") {
$hits = new \ArrayObject($index->find($this->buildQuery($keyword, $options)));
$hits = new \ArrayObject($index->find($query));
} else {
$hits = new \ArrayObject($index->find($this->buildQuery($keyword, $options), $options['sortField']));
$hits = new \ArrayObject($index->find($query, $options['sortField']));
}
$resultSet = new SearchResultSet();
@ -134,19 +142,26 @@ class ZendLuceneSearch extends Search
return $resultSet;
}
/**
* Returns the lucence search query
*
* @param string $keyword
* @param array $options
* @return \ZendSearch\Lucene\Search\Query\AbstractQuery
*/
protected function buildQuery($keyword, $options)
{
// Allow *Token*
\ZendSearch\Lucene\Search\Query\Wildcard::setMinPrefixLength(0);
$query = new \ZendSearch\Lucene\Search\Query\Boolean();
foreach (explode(" ", $keyword) as $k) {
// Require at least 3 non-wildcard characters
if (strlen($k) > 2) {
$term = new \ZendSearch\Lucene\Index\Term("*" . $k . "*");
$query->addSubquery(new \ZendSearch\Lucene\Search\Query\Wildcard($term), true);
if (strlen($k) < $this->minQueryTokenLength) {
return null;
}
$term = new \ZendSearch\Lucene\Index\Term("*" . $k . "*");
$query->addSubquery(new \ZendSearch\Lucene\Search\Query\Wildcard($term), true);
}
// Add model filter

View File

@ -2,25 +2,45 @@
/**
* @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
*/
namespace humhub\modules\search\libs;
/**
* Description of SearchResult
* SearchResultSet
*
* @author luke
*/
class SearchResultSet
{
/**
* @var SearchResult[] the search rsults
*/
public $results = array();
public $total;
public $page;
/**
* @var int number of total results
*/
public $total = 0;
/**
* @var int the current page
*/
public $page = 1;
/**
* @var int page size
*/
public $pageSize;
/**
* Returns active record instances of the search results
*
* @return \yii\db\ActiveRecord
*/
public function getResultInstances()
{
$instances = array();

View File

@ -5,7 +5,6 @@ use yii\helpers\Html;
use humhub\modules\search\controllers\SearchController;
use humhub\modules\content\components\ContentActiveRecord;
use humhub\modules\content\components\ContentContainerActiveRecord;
?>
<div class="container">
<div class="row">
@ -111,7 +110,13 @@ use humhub\modules\content\components\ContentContainerActiveRecord;
<?php endif; ?>
<?php endforeach; ?>
<?php else: ?>
<p>Sorry nothing found :(</p>
<div class="panel panel-default">
<div class="panel-body">
<p><strong><?php echo Yii::t('SearchModule.views_search_index', 'Your search returned no matches.'); ?></strong></p>
</div>
</div>
<?php endif; ?>
</div>
@ -127,7 +132,7 @@ use humhub\modules\content\components\ContentContainerActiveRecord;
<script type="text/javascript">
$( document ).ready(function() {
$(document).ready(function () {
// set focus to input for seach field
$('#search-input-field').focus();
});
@ -150,11 +155,11 @@ use humhub\modules\content\components\ContentContainerActiveRecord;
});
<?php foreach (explode(" ", $keyword) as $k) : ?>
$(".searchResults").highlight("<?php echo Html::encode($k); ?>");
$(document).ajaxComplete(function (event, xhr, settings) {
<?php foreach (explode(" ", $keyword) as $k) : ?>
$(".searchResults").highlight("<?php echo Html::encode($k); ?>");
});
<?php endforeach; ?>
$(document).ajaxComplete(function (event, xhr, settings) {
$(".searchResults").highlight("<?php echo Html::encode($k); ?>");
});
<?php endforeach; ?>
</script>

View File

@ -1,18 +1,27 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\modules\space\widgets;
use humhub\widgets\BaseSidebar;
/**
* SpaceSidebarWidget is a extended StackWidget which allows modifications of the
* space sidebars.
*
* Sidebar implements the default space sidebar.
*
* @author Luke
* @package humhub.modules_core.space.widgets
* @since 0.5
*/
class Sidebar extends \humhub\widgets\BaseStack
class Sidebar extends BaseSidebar
{
/**
* @var \humhub\modules\space\models\Space the space this sidebar is in
*/
public $space;
}

View File

@ -79,7 +79,7 @@ AppAsset::register($this);
$('body').find(':checkbox, :radio').flatelements();
</script>
<?php echo Yii::$app->settings->get('trackingHtmlCode'); ?>
<?= \humhub\widgets\LayoutAddons::widget(); ?>
<?php $this->endBody() ?>
<div class="text text-center powered">
Powered by <a href="http://www.humhub.org" target="_blank">HumHub</a>

View File

@ -1,15 +1,27 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\modules\user\widgets;
use humhub\widgets\BaseSidebar;
/**
* @package humhub.modules_core.user.widgets
* ProfileSidebar implements the sidebar for the user profiles.
*
* @since 0.5
* @author Luke
*/
class ProfileSidebar extends \humhub\widgets\BaseStack
class ProfileSidebar extends BaseSidebar
{
/**
* @var \humhub\modules\user\models\User the user this sidebar belongs to
*/
public $user;
}

View File

@ -9,8 +9,8 @@ use humhub\assets\AppAsset;
AppAsset::register($this);
?>
<?php $this->beginPage() ?>
<!DOCTYPE html>
<html lang="en">
<!DOCTYPE html>
<html lang="en">
<head>
<!-- start: Meta -->
<meta charset="utf-8">
@ -80,78 +80,62 @@ AppAsset::register($this);
</head>
<body>
<?php $this->beginBody() ?>
<?php $this->beginBody() ?>
<!-- start: first top navigation bar -->
<div id="topbar-first" class="topbar">
<div class="container">
<div class="topbar-brand hidden-xs">
<?php echo \humhub\widgets\SiteLogo::widget(); ?>
</div>
<div class="topbar-actions pull-right">
<?php echo \humhub\modules\user\widgets\AccountTopMenu::widget(); ?>
</div>
<div class="notifications pull-right">
<?php
echo \humhub\widgets\NotificationArea::widget(['widgets' => [
[\humhub\modules\notification\widgets\Overview::className(), [], ['sortOrder' => 10]],
]]);
?>
</div>
</div>
</div>
<!-- end: first top navigation bar -->
<!-- start: second top navigation bar -->
<div id="topbar-second" class="topbar">
<div class="container">
<ul class="nav ">
<!-- load space chooser widget -->
<?php echo \humhub\modules\space\widgets\Chooser::widget(); ?>
<!-- load navigation from widget -->
<?php echo \humhub\widgets\TopMenu::widget(); ?>
</ul>
<ul class="nav pull-right" id="search-menu-nav">
<?php echo \humhub\widgets\TopMenuRightStack::widget(); ?>
</ul>
</div>
</div>
<!-- end: second top navigation bar -->
<?php echo \humhub\modules\tour\widgets\Tour::widget(); ?>
<!-- start: show content (and check, if exists a sublayout -->
<?php if (isset($this->context->subLayout) && $this->context->subLayout != "") : ?>
<?php echo $this->render($this->context->subLayout, array('content' => $content)); ?>
<?php else: ?>
<?php echo $content; ?>
<?php endif; ?>
<!-- end: show content -->
<!-- start: Modal (every lightbox will/should use this construct to show content)-->
<div class="modal" id="globalModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<?php echo \humhub\widgets\LoaderWidget::widget(); ?>
<!-- start: first top navigation bar -->
<div id="topbar-first" class="topbar">
<div class="container">
<div class="topbar-brand hidden-xs">
<?php echo \humhub\widgets\SiteLogo::widget(); ?>
</div>
<div class="topbar-actions pull-right">
<?php echo \humhub\modules\user\widgets\AccountTopMenu::widget(); ?>
</div>
<div class="notifications pull-right">
<?php
echo \humhub\widgets\NotificationArea::widget(['widgets' => [
[\humhub\modules\notification\widgets\Overview::className(), [], ['sortOrder' => 10]],
]]);
?>
</div>
</div>
</div>
<!-- end: first top navigation bar -->
<!-- start: second top navigation bar -->
<div id="topbar-second" class="topbar">
<div class="container">
<ul class="nav ">
<!-- load space chooser widget -->
<?php echo \humhub\modules\space\widgets\Chooser::widget(); ?>
<!-- load navigation from widget -->
<?php echo \humhub\widgets\TopMenu::widget(); ?>
</ul>
<ul class="nav pull-right" id="search-menu-nav">
<?php echo \humhub\widgets\TopMenuRightStack::widget(); ?>
</ul>
</div>
</div>
</div>
<!-- end: Modal -->
<!-- end: second top navigation bar -->
<?php echo Yii::$app->settings->get('trackingHtmlCode'); ?>
<?php $this->endBody() ?>
<!-- start: show content (and check, if exists a sublayout -->
<?php if (isset($this->context->subLayout) && $this->context->subLayout != "") : ?>
<?php echo $this->render($this->context->subLayout, array('content' => $content)); ?>
<?php else: ?>
<?php echo $content; ?>
<?php endif; ?>
<!-- end: show content -->
<?= \humhub\widgets\LayoutAddons::widget(); ?>
<?php $this->endBody() ?>
</body>
</html>
</html>
<?php $this->endPage() ?>

View File

@ -0,0 +1,20 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\widgets;
/**
* BaseSidebar
*
* @since 1.1
* @author Luke
*/
class BaseSidebar extends BaseStack
{
}

View File

@ -71,7 +71,7 @@ class BaseStack extends \yii\base\Widget
public function init()
{
$this->trigger(self::EVENT_INIT);
return parent::init();
parent::init();
}
/**

View File

@ -0,0 +1,30 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\widgets;
/**
* GlobalModal is the standard modal which can be used in every layout.
* This widget is automatically added to the page via the LayoutAddons.
*
* @see LayoutAddons
* @author Luke
* @since 1.1
*/
class GlobalModal extends \yii\base\Widget
{
/**
* @inheritdoc
*/
public function run()
{
return $this->render('globalModal');
}
}

View File

@ -0,0 +1,31 @@
<?php
/**
* @link https://www.humhub.org/
* @copyright Copyright (c) 2016 HumHub GmbH & Co. KG
* @license https://www.humhub.com/licences
*/
namespace humhub\widgets;
/**
* LayoutAddons are inserted at the end of all layouts (standard or login).
*
* @since 1.1
* @author Luke
*/
class LayoutAddons extends BaseStack
{
/**
* @inheritdoc
*/
public function init()
{
$this->addWidget(GlobalModal::className());
$this->addWidget(\humhub\modules\tour\widgets\Tour::className());
$this->addWidget(\humhub\modules\admin\widgets\TrackingWidget::className());
parent::init();
}
}

View File

@ -0,0 +1,9 @@
<div class="modal" id="globalModal" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-body">
<?php echo \humhub\widgets\LoaderWidget::widget(); ?>
</div>
</div>
</div>
</div>