Merge branch 'master' into develop

This commit is contained in:
Lucas Bartholemy 2024-07-22 10:26:06 +02:00
commit 84e05c9a87
10 changed files with 99 additions and 25 deletions

View File

@ -12,6 +12,12 @@ HumHub Changelog
---------------------
- Fix #7102: Fix content search with word ending with hyphen
- Fix #7104: Missing `--text-color-default` CSS variable
- Enh #7105: Add an external link icon to the "Install Updates" button to avoid thinking it updates the modules directly
- Fix #7116: Fix rebuilding the search index with Grunt (since 1.16.0)
- Fix #7120: Error after failed migration of content fulltext index
- Fix #7126: Fix member count on a space directory
- Enh #6794: Improve log wrong parsing of OEmbed URL
- Fix #6794: Add `User-Agent` to oEmbed CURL request (fix for Reddit)
1.16.1 (July 1, 2024)
---------------------

View File

@ -6,11 +6,11 @@ module.exports = function (grunt) {
var cssMinAssetcfg = {};
cssMinAssetcfg[grunt.option('to')] = [grunt.option('from')];
var isWin = function() {
var isWin = function () {
return (process.platform === "win32");
};
var cmdSep = function() {
var cmdSep = function () {
return isWin() ? '&' : ';';
};
@ -19,7 +19,7 @@ module.exports = function (grunt) {
clean: ["assets/*"],
shell: {
buildAssets: {
command: function() {
command: function () {
let rm = isWin() ? 'del' : 'rm';
let sep = cmdSep();
let delAssets = isWin() ? '(For /D %i in (static\\assets\\*.*) do (rmdir %i /S /Q))' : `${rm} -rf static/assets/*/`;
@ -30,18 +30,18 @@ module.exports = function (grunt) {
}
},
buildSearch: {
command: function() {
command: function () {
let sep = cmdSep();
return `cd protected ${sep} php yii search/rebuild`;
return `cd protected ${sep} php yii content-search/rebuild`;
}
},
testServer: {
command: "php -S localhost:8080 index-test.php"
},
testRun: {
command: function() {
command: function () {
let sep = cmdSep();
let moduleName = grunt.option('module') || grunt.option('m') || null;
let moduleName = grunt.option('module') || grunt.option('m') || null;
let doBuild = grunt.option('build') || false;
let base = process.cwd();
@ -49,7 +49,7 @@ module.exports = function (grunt) {
let rootTestPath = `${base}/protected/humhub/tests`;
let testPath = rootTestPath;
if(moduleName) {
if (moduleName) {
testPath = `${base}/protected/humhub/modules/${moduleName}/tests`;
}
@ -57,10 +57,10 @@ module.exports = function (grunt) {
let path = grunt.option('path') || null;
let executionPath = '';
if(suite) {
if (suite) {
executionPath = suite;
} else if(path) {
if(path.indexOf('codeception') !== 0) {
} else if (path) {
if (path.indexOf('codeception') !== 0) {
path = 'codeception' + ((path.indexOf('/') !== 0) ? '/' : '') + path;
}
executionPath = path;
@ -69,10 +69,10 @@ module.exports = function (grunt) {
let options = grunt.option('options') || '';
options += grunt.option('raw') ? ' --no-ansi' : '';
options += grunt.option('debug') ? ' -d' : '';
options += grunt.option('env') ? ' --env '+ grunt.option('env') : '';
options += grunt.option('env') ? ' --env ' + grunt.option('env') : '';
let build = `cd ${rootTestPath} ${sep} php ${codeceptPath} build`;
let build = `cd ${rootTestPath} ${sep} php ${codeceptPath} build`;
let run = `cd ${testPath} ${sep} php ${codeceptPath} run ${executionPath} ${options}`;
@ -80,21 +80,21 @@ module.exports = function (grunt) {
}
},
buildTheme: {
command: function(name) {
command: function (name) {
let theme = name || grunt.option('name') || "HumHub";
let sep = cmdSep();
return `cd themes/${theme}/less ${sep} lessc -x build.less ../css/theme.css`;
}
},
migrateCreate: {
command: function(name) {
command: function (name) {
let migrationName = name || grunt.option('name');
let sep = cmdSep();
return `cd protected ${sep} php yii migrate/create ${migrationName}`;
}
},
migrateUp: {
command: function(modules) {
command: function (modules) {
let includeModuleMigrations = modules || grunt.option('modules') || "1";
let sep = cmdSep();
return `cd protected ${sep} php yii migrate/up --includeModuleMigrations=${includeModuleMigrations}`;

View File

@ -24,6 +24,7 @@ class UrlOembedHttpClient implements UrlOembedClient
$curl = curl_init($url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_TIMEOUT, 15);
curl_setopt($curl, CURLOPT_USERAGENT, Yii::$app->name);
// Not available when open_basedir is set.
if (!function_exists('ini_get') || !ini_get('open_basedir')) {
@ -62,7 +63,8 @@ class UrlOembedHttpClient implements UrlOembedClient
return Json::decode($json);
}
} catch (\Exception $ex) {
Yii::warning($ex);
Yii::warning("Error decoding JSON from OEmbed URL:\n" . $json .
"\n\n" . $ex->getTraceAsString());
}
return null;

View File

@ -51,6 +51,10 @@ class m220121_193617_oembed_setting_update extends Migration
'pattern' => '/slideshare\.net/',
'endpoint' => 'https://www.slideshare.net/api/oembed/2?url=%url%&format=json&maxwidth=450',
],
'Reddit' => [
'pattern' => '/reddit\.com/',
'endpoint' => 'https://www.reddit.com/oembed?format=json&url=%url%',
],
];
foreach (UrlOembed::getProviders() as $providerUrl => $providerEndpoint) {

View File

@ -10,7 +10,7 @@ use humhub\modules\marketplace\widgets\MarketplaceLink;
/* @var int $count */
?>
<div class="modules-updates-info">
<?= MarketplaceLink::warning(Yii::t('AdminModule.base', 'Install Updates'))->right()->sm() ?>
<?= MarketplaceLink::warning(Yii::t('AdminModule.base', 'Install Updates'))->icon('external-link')->right()->sm() ?>
<strong><?= Yii::t('AdminModule.base', 'Updates available for {count} of your modules', ['count' => $count]) ?></strong><br>
<?= Yii::t('AdminModule.base', 'Keep your system up-to-date and benefit from the latest improvements.') ?>
</div>

View File

@ -57,10 +57,7 @@ class CommentForm extends yii\base\Model
}
/**
* @param null $attributeNames
* @param bool $clearErrors
* @return bool
* @throws ServerErrorHttpException
* @inheritdoc
*/
public function validate($attributeNames = null, $clearErrors = true)
{
@ -70,6 +67,7 @@ class CommentForm extends yii\base\Model
if (!$this->comment->validate() || !parent::validate($attributeNames, $clearErrors)) {
$this->comment->addError('message', Yii::t('CommentModule.base', 'Comment could not be saved!'));
return false;
}
if (!empty($this->comment->message)) {
@ -82,6 +80,7 @@ class CommentForm extends yii\base\Model
}
$this->comment->addError('message', Yii::t('CommentModule.base', 'The comment must not be empty!'));
return false;
}
/**

View File

@ -0,0 +1,42 @@
<?php
use humhub\components\Migration;
use humhub\modules\content\jobs\SearchRebuildIndex;
use humhub\modules\file\libs\FileHelper;
/**
* Class m240715_150726_fulltext_index
*/
class m240715_150726_fulltext_index extends Migration
{
/**
* {@inheritdoc}
*/
public function safeUp()
{
// Try to create the fulltext index again only if it was not created correctly in previous migration
if ($this->indexExists('ftx', 'content_fulltext')) {
return;
}
try {
$this->execute('ALTER TABLE content_fulltext ADD FULLTEXT INDEX ftx (contents, comments, files)');
Yii::$app->queue->push(new SearchRebuildIndex());
FileHelper::removeDirectory(Yii::getAlias('@runtime/searchdb'));
} catch (\Exception $ex) {
Yii::error('Could not execute content fulltext search migration: ' . $ex->getMessage());
}
}
/**
* {@inheritdoc}
*/
public function safeDown()
{
echo "m240715_150726_fulltext_index cannot be reverted.\n";
return false;
}
}

View File

@ -11,6 +11,7 @@ use humhub\modules\space\models\Membership;
use humhub\modules\space\models\Space;
use humhub\modules\user\components\ActiveQueryUser;
use humhub\modules\user\models\User;
use Yii;
/**
* @since 1.14
@ -34,6 +35,18 @@ class MemberListService
return Membership::getSpaceMembersQuery($this->space, true, $withNotifications);
}
public function getReadableQuery(?User $user = null): ActiveQueryUser
{
$query = Membership::getSpaceMembersQuery($this->space);
if (Yii::$app->user->isGuest) {
return $query->active()
->andWhere(['!=', 'user.visibility', User::VISIBILITY_HIDDEN]);
}
return $query->visible($user);
}
public function getQuery(?User $user = null): ActiveQueryUser
{
return Membership::getSpaceMembersQuery($this->space)->visible($user);
@ -44,8 +57,8 @@ class MemberListService
return $this->getQuery($user)->filterBlockedUsers($user);
}
public function getCount(): int
public function getCount(?User $user = null): int
{
return $this->getQuery()->count();
return $this->getQuery($user)->count();
}
}

View File

@ -34,7 +34,11 @@ class SpaceDirectoryIcons extends Widget
}
$membership = $this->space->getMembership();
$membersCount = $this->space->getMemberListService()->getCount();
$membersCountQuery = $this->space->getMemberListService()->getReadableQuery();
$membersCount = Yii::$app->runtimeCache->getOrSet(__METHOD__ . Yii::$app->user->id . '-' . $this->space->id, function () use ($membersCountQuery) {
return $membersCountQuery->count();
});
return $this->render('spaceDirectoryIcons', [
'space' => $this->space,

View File

@ -70,6 +70,10 @@ return [
'pattern' => '/slideshare\.net/',
'endpoint' => 'https://www.slideshare.net/api/oembed/2?url=%url%&format=json&maxwidth=450',
],
'Reddit' => [
'pattern' => '/reddit\.com/',
'endpoint' => 'https://www.reddit.com/oembed?format=json&url=%url%',
],
]), 'module_id' => 'base'],
['name' => 'defaultLanguage', 'value' => 'en-US', 'module_id' => 'base'],
['name' => 'maintenanceMode', 'value' => '0', 'module_id' => 'base'],