mirror of
https://github.com/humhub/humhub.git
synced 2025-04-21 15:41:54 +02:00
Improve settings handling and add tests (#6270)
* Fix #6266: BaseSettingsManager::deleteAll() does use prefix as wildcard * Enh #6271: Add input and type checks, as well as strict types to SettingsManager * Fix #6267 SettingsManager::flushContentContainer() only clears the collection in the current instance, not the underlying cache * Enh #6272: Always return integer from settings, if value can be converted * Improve \humhub\libs\BaseSettingsManager::getSerialized() to allow return value be an object and throw an exception on decoding error * Enh #6270: Add tests for SettingsManager
This commit is contained in:
parent
184c33ad46
commit
1b0700deed
@ -3,6 +3,11 @@ HumHub Changelog
|
||||
|
||||
1.15.0 (Unreleased)
|
||||
-------------------
|
||||
- Enh #6270: Add tests for SettingsManager
|
||||
- Enh #6272: Always return integer from settings, if value can be converted
|
||||
- Fix #6267: SettingsManager::flushContentContainer() only clears the collection in the current instance, not the underlying cache
|
||||
- Enh #6271: Add input and type checks, as well as strict types to SettingsManager
|
||||
- Fix #6266: BaseSettingsManager::deleteAll() does use prefix as wildcard
|
||||
- Fix #6259: Add json & pdo extensions as requirement; updating composer dependencies and node modules
|
||||
- Fix #6192: Where Group::getAdminGroupId() would sometimes return int, sometimes string
|
||||
- Enh #6260: Improve migration class
|
||||
|
18
MIGRATE-DEV.md
Normal file
18
MIGRATE-DEV.md
Normal file
@ -0,0 +1,18 @@
|
||||
Module Migration Guide
|
||||
======================
|
||||
|
||||
See [humhub/documentation::docs/develop/modules-migrate.md](https://github.com/humhub/documentation/blob/master/docs/develop/modules-migrate.md)
|
||||
for full version.
|
||||
|
||||
Version 1.15 (Unreleased)
|
||||
-------------------------
|
||||
|
||||
### Behaviour change
|
||||
- `\humhub\libs\BaseSettingsManager::deleteAll()` no longer uses the `$prefix` parameter as a full wildcard, but
|
||||
actually as a prefix. Use `$prefix = '%pattern%'` to get the old behaviour. Or use `$parameter = '%suffix'` if you
|
||||
want to match against the end of the names.
|
||||
- `\humhub\libs\BaseSettingsManager::get()` now returns a pure int in case the (trimmed) value can be converted
|
||||
|
||||
|
||||
### Type restrictions
|
||||
- `\humhub\libs\BaseSettingsManager` and its child classes on fields, method parameters, & return types
|
@ -9,6 +9,7 @@
|
||||
namespace humhub\components;
|
||||
|
||||
use Yii;
|
||||
use yii\base\InvalidCallException;
|
||||
use yii\db\ActiveRecord;
|
||||
|
||||
/**
|
||||
@ -22,24 +23,38 @@ abstract class SettingActiveRecord extends ActiveRecord
|
||||
/**
|
||||
* @const array List of fields to be used to generate the cache key
|
||||
*/
|
||||
protected const CACHE_KEY_FIELDS = ['module_id'];
|
||||
public const CACHE_KEY_FIELDS = ['module_id'];
|
||||
|
||||
/**
|
||||
* @const string Used as the formatting pattern for sprintf when generating the cache key
|
||||
*/
|
||||
protected const CACHE_KEY_FORMAT = 'settings-%s';
|
||||
public const CACHE_KEY_FORMAT = 'settings-%s';
|
||||
|
||||
/**
|
||||
* @param string|array|null $condition
|
||||
* @param array $params
|
||||
*
|
||||
* @return int
|
||||
* @noinspection PhpMissingReturnTypeInspection
|
||||
*/
|
||||
public static function deleteAll($condition = null, $params = [])
|
||||
{
|
||||
if (static::class === self::class) {
|
||||
throw new InvalidCallException(sprintf(
|
||||
'Method %s may not be called from the abstract class, but MUST be called from the implementing class, as otherwise tablename() is not returning a correct table.',
|
||||
__METHOD__
|
||||
));
|
||||
}
|
||||
|
||||
// get a grouped list of cache entries that are going to be deleted, grouped by static::CACHE_KEY_FIELDS
|
||||
$containers = self::find()
|
||||
$modulesOrContainers = self::find()
|
||||
->where($condition, $params)
|
||||
->groupBy(static::CACHE_KEY_FIELDS)
|
||||
->select(static::CACHE_KEY_FIELDS)
|
||||
->all();
|
||||
|
||||
// going through that list, deleting the respective cache
|
||||
array_walk($containers, static function (ActiveRecord $rec) {
|
||||
array_walk($modulesOrContainers, static function (ActiveRecord $rec) {
|
||||
$key = static::getCacheKey(...array_values($rec->toArray()));
|
||||
Yii::$app->cache->delete($key);
|
||||
});
|
||||
@ -49,8 +64,8 @@ abstract class SettingActiveRecord extends ActiveRecord
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $moduleId Name of the module to create the cache key for
|
||||
* @param mixed ...$values Additional arguments, if required by the static::CACHE_KEY_FORMAT
|
||||
* @param string $moduleId Name of the module to create the cache key for
|
||||
* @param mixed ...$values Additional arguments, if required by the static::CACHE_KEY_FORMAT
|
||||
*
|
||||
* @return string The key used for cache operation
|
||||
*/
|
||||
|
@ -8,6 +8,10 @@
|
||||
|
||||
namespace humhub\components;
|
||||
|
||||
use humhub\modules\content\components\ContentContainerController;
|
||||
use humhub\modules\space\models\Space;
|
||||
use humhub\modules\user\models\User;
|
||||
use Throwable;
|
||||
use Yii;
|
||||
use humhub\libs\BaseSettingsManager;
|
||||
use humhub\modules\content\components\ContentContainerActiveRecord;
|
||||
@ -21,11 +25,10 @@ use humhub\modules\content\components\ContentContainerSettingsManager;
|
||||
*/
|
||||
class SettingsManager extends BaseSettingsManager
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ContentContainerSettingsManager[] already loaded content container settings managers
|
||||
*/
|
||||
protected $contentContainers = [];
|
||||
protected array $contentContainers = [];
|
||||
|
||||
/**
|
||||
* Returns content container
|
||||
@ -33,18 +36,16 @@ class SettingsManager extends BaseSettingsManager
|
||||
* @param ContentContainerActiveRecord $container
|
||||
* @return ContentContainerSettingsManager
|
||||
*/
|
||||
public function contentContainer(ContentContainerActiveRecord $container)
|
||||
public function contentContainer(ContentContainerActiveRecord $container): ContentContainerSettingsManager
|
||||
{
|
||||
if (isset($this->contentContainers[$container->contentcontainer_id])) {
|
||||
return $this->contentContainers[$container->contentcontainer_id];
|
||||
if ($contentContainers = $this->contentContainers[$container->contentcontainer_id] ?? null) {
|
||||
return $contentContainers;
|
||||
}
|
||||
|
||||
$this->contentContainers[$container->contentcontainer_id] = new ContentContainerSettingsManager([
|
||||
return $this->contentContainers[$container->contentcontainer_id] = new ContentContainerSettingsManager([
|
||||
'moduleId' => $this->moduleId,
|
||||
'contentContainer' => $container,
|
||||
]);
|
||||
|
||||
return $this->contentContainers[$container->contentcontainer_id];
|
||||
}
|
||||
|
||||
|
||||
@ -52,24 +53,38 @@ class SettingsManager extends BaseSettingsManager
|
||||
* Clears runtime cached content container settings
|
||||
*
|
||||
* @param ContentContainerActiveRecord|null $container if null all content containers will be flushed
|
||||
*
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function flushContentContainer(ContentContainerActiveRecord $container = null)
|
||||
{
|
||||
if ($container === null) {
|
||||
$containers = $this->contentContainers;
|
||||
$this->contentContainers = [];
|
||||
} else {
|
||||
// need to create an instance, if it does not already exist, in order to then flush the underlying cache
|
||||
$containers = [$this->contentContainer($container)] ?? null;
|
||||
unset($this->contentContainers[$container->contentcontainer_id]);
|
||||
}
|
||||
|
||||
array_walk($containers, static fn(ContentContainerSettingsManager $container) => $container->invalidateCache());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns ContentContainerSettingsManager for the given $user or current logged in user
|
||||
* @return ContentContainerSettingsManager
|
||||
* Returns ContentContainerSettingsManager for the given $user or current logged-in user
|
||||
*
|
||||
* @param User|null $user
|
||||
*
|
||||
* @return ContentContainerSettingsManager|null
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function user($user = null)
|
||||
public function user(?User $user = null): ?ContentContainerSettingsManager
|
||||
{
|
||||
if (!$user) {
|
||||
if ($user === null) {
|
||||
$user = Yii::$app->user->getIdentity();
|
||||
if (!$user instanceof User) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->contentContainer($user);
|
||||
@ -77,27 +92,37 @@ class SettingsManager extends BaseSettingsManager
|
||||
|
||||
/**
|
||||
* Returns ContentContainerSettingsManager for the given $space or current controller space
|
||||
*
|
||||
* @param Space|null $space
|
||||
*
|
||||
* @return ContentContainerSettingsManager
|
||||
*/
|
||||
public function space($space = null)
|
||||
public function space(?Space $space = null): ?ContentContainerSettingsManager
|
||||
{
|
||||
if ($space != null) {
|
||||
if ($space !== null) {
|
||||
return $this->contentContainer($space);
|
||||
} elseif (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);
|
||||
}
|
||||
}
|
||||
|
||||
/** @noinspection PhpPossiblePolymorphicInvocationInspection */
|
||||
if (
|
||||
($controller = Yii::$app->controller) instanceof ContentContainerController
|
||||
&& ($space = $controller->contentContainer) instanceof Space
|
||||
) {
|
||||
return $this->contentContainer($space);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates this setting is fixed in configuration file and cannot be
|
||||
* changed at runtime.
|
||||
*
|
||||
* @param string $name
|
||||
* @param string|int $name
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public function isFixed($name)
|
||||
public function isFixed(string $name): bool
|
||||
{
|
||||
return isset(Yii::$app->params['fixed-settings'][$this->moduleId][$name]);
|
||||
}
|
||||
|
@ -523,4 +523,4 @@ return [
|
||||
'defer',
|
||||
],
|
||||
],
|
||||
];
|
||||
];
|
||||
|
35
protected/humhub/exceptions/InvalidArgumentTypeException.php
Normal file
35
protected/humhub/exceptions/InvalidArgumentTypeException.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2023 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\exceptions;
|
||||
|
||||
use yii\base\InvalidArgumentException;
|
||||
|
||||
/**
|
||||
* @since 1.15
|
||||
*/
|
||||
class InvalidArgumentTypeException extends InvalidArgumentException
|
||||
{
|
||||
use InvalidTypeExceptionTrait;
|
||||
|
||||
protected function formatPrologue(array $constructArguments): string
|
||||
{
|
||||
$argumentName = is_array($this->parameter)
|
||||
? reset($this->parameter)
|
||||
: null;
|
||||
$argumentNumber = is_array($this->parameter)
|
||||
? key($this->parameter)
|
||||
: $this->parameter;
|
||||
|
||||
$argumentName = $argumentName === null
|
||||
? ''
|
||||
: " \$" . ltrim($argumentName, '$');
|
||||
|
||||
return sprintf('Argument #%d%s', $argumentNumber, $argumentName);
|
||||
}
|
||||
}
|
24
protected/humhub/exceptions/InvalidConfigTypeException.php
Normal file
24
protected/humhub/exceptions/InvalidConfigTypeException.php
Normal file
@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2023 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\exceptions;
|
||||
|
||||
use yii\base\InvalidConfigException;
|
||||
|
||||
/**
|
||||
* @since 1.15
|
||||
*/
|
||||
class InvalidConfigTypeException extends InvalidConfigException
|
||||
{
|
||||
use InvalidTypeExceptionTrait;
|
||||
|
||||
protected function formatPrologue(array $constructArguments): string
|
||||
{
|
||||
return "Parameter $this->parameter of configuration";
|
||||
}
|
||||
}
|
75
protected/humhub/exceptions/InvalidTypeExceptionTrait.php
Normal file
75
protected/humhub/exceptions/InvalidTypeExceptionTrait.php
Normal file
@ -0,0 +1,75 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2023 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\exceptions;
|
||||
|
||||
/**
|
||||
* @since 1.15
|
||||
*/
|
||||
trait InvalidTypeExceptionTrait
|
||||
{
|
||||
// public properties
|
||||
|
||||
public string $methodName;
|
||||
public $parameter;
|
||||
public array $validType = [];
|
||||
|
||||
/**
|
||||
* @var mixed|null
|
||||
*/
|
||||
public $givenValue;
|
||||
|
||||
/**
|
||||
* @param string $method
|
||||
* @param int|array $parameter = [
|
||||
* int => string, // position, or [ position => name ] of the argument
|
||||
* ]
|
||||
* @param array|string|null $validType
|
||||
* @param null $givenValue
|
||||
*/
|
||||
public function __construct(
|
||||
$method = '',
|
||||
$parameter = null,
|
||||
$validType = [],
|
||||
$givenValue = null,
|
||||
$nullable = false,
|
||||
$code = 0,
|
||||
$previous = null
|
||||
) {
|
||||
|
||||
$this->methodName = $method;
|
||||
$this->parameter = $parameter;
|
||||
$this->validType = (array)($validType ?? ['mixed']);
|
||||
$this->givenValue = $givenValue;
|
||||
|
||||
if ($nullable && !in_array('null', $this->validType, true)) {
|
||||
$this->validType[] = 'null';
|
||||
}
|
||||
|
||||
$message = sprintf(
|
||||
'%s passed to %s must be of type %s, %s given.',
|
||||
$this->formatPrologue(func_get_args()),
|
||||
$this->methodName,
|
||||
implode(', ', $this->validType),
|
||||
get_debug_type($this->givenValue)
|
||||
);
|
||||
|
||||
parent::__construct($message, $code, $previous);
|
||||
}
|
||||
|
||||
abstract protected function formatPrologue(array $constructArguments): string;
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
if (method_exists(parent::class, 'getName')) {
|
||||
return parent::getName() . " Type";
|
||||
}
|
||||
|
||||
return 'Invalid Type';
|
||||
}
|
||||
}
|
@ -9,10 +9,12 @@
|
||||
namespace humhub\libs;
|
||||
|
||||
use humhub\components\SettingActiveRecord;
|
||||
use humhub\exceptions\InvalidArgumentTypeException;
|
||||
use Stringable;
|
||||
use Yii;
|
||||
use yii\base\Component;
|
||||
use yii\base\Exception;
|
||||
use yii\base\InvalidArgumentException;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\db\conditions\LikeCondition;
|
||||
use yii\db\StaleObjectException;
|
||||
use yii\helpers\Json;
|
||||
@ -26,9 +28,9 @@ use yii\helpers\Json;
|
||||
abstract class BaseSettingsManager extends Component
|
||||
{
|
||||
/**
|
||||
* @var string|null module id this settings manager belongs to.
|
||||
* @var string module id this settings manager belongs to.
|
||||
*/
|
||||
public ?string $moduleId = null;
|
||||
public string $moduleId;
|
||||
|
||||
/**
|
||||
* @var array|null of loaded settings
|
||||
@ -45,15 +47,20 @@ abstract class BaseSettingsManager extends Component
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
if ($this->moduleId === null) {
|
||||
throw new Exception('Could not determine module id');
|
||||
try {
|
||||
if ($this->moduleId === '') {
|
||||
throw new InvalidConfigException('Empty module id!', 1);
|
||||
}
|
||||
} catch (InvalidConfigException $t) {
|
||||
throw $t;
|
||||
} catch (\Throwable $t) {
|
||||
throw new InvalidConfigException('Module id not set!', 2);
|
||||
}
|
||||
|
||||
if (static::isDatabaseInstalled()) {
|
||||
$this->loadValues();
|
||||
}
|
||||
|
||||
|
||||
parent::init();
|
||||
}
|
||||
|
||||
@ -61,12 +68,21 @@ abstract class BaseSettingsManager extends Component
|
||||
* Sets a settings value
|
||||
*
|
||||
* @param string $name
|
||||
* @param string $value
|
||||
* @param string|int|bool $value
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function set($name, $value)
|
||||
public function set(string $name, $value)
|
||||
{
|
||||
if ($name === '') {
|
||||
throw new InvalidArgumentException(
|
||||
sprintf('Argument #1 ($name) passed to %s may not be an empty string!', __METHOD__)
|
||||
);
|
||||
}
|
||||
|
||||
if ($value === null) {
|
||||
return $this->delete($name);
|
||||
$this->delete($name);
|
||||
return;
|
||||
}
|
||||
|
||||
// Update database setting record
|
||||
@ -107,15 +123,23 @@ abstract class BaseSettingsManager extends Component
|
||||
*
|
||||
* @param string $name
|
||||
* @param mixed $default the setting value or null when not exists
|
||||
* @param bool $asArray whether to return objects in terms of associative arrays.
|
||||
* @param bool $throwException if true then throw an exception upon error, rather than returning the serialized string
|
||||
*
|
||||
* @return mixed|string|null
|
||||
*/
|
||||
public function getSerialized(string $name, $default = null)
|
||||
public function getSerialized(string $name, $default = null, bool $asArray = true, bool $throwException = false)
|
||||
{
|
||||
$value = $this->get($name, $default);
|
||||
if (is_string($value)) {
|
||||
try {
|
||||
$value = Json::decode($value);
|
||||
$value = Json::decode($value, $asArray);
|
||||
} catch (InvalidArgumentException $ex) {
|
||||
Yii::error($ex->getMessage());
|
||||
|
||||
if ($throwException) {
|
||||
throw $ex;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $value;
|
||||
@ -124,13 +148,16 @@ abstract class BaseSettingsManager extends Component
|
||||
/**
|
||||
* Returns value of setting
|
||||
*
|
||||
* @param string $name the name of setting
|
||||
* @param string|int $name the name of setting
|
||||
*
|
||||
* @return string|null the setting value or null when not exists
|
||||
* @return string|mixed|null the setting value or null when not exists
|
||||
*/
|
||||
public function get(string $name, $default = null)
|
||||
{
|
||||
return $this->_loaded[$name] ?? $default;
|
||||
$value = $this->_loaded[$name] ?? null;
|
||||
|
||||
// make sure it is an int, if it is possible
|
||||
return filter_var($value, FILTER_VALIDATE_INT, FILTER_NULL_ON_FAILURE) ?? $value ?? $default;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -243,18 +270,34 @@ abstract class BaseSettingsManager extends Component
|
||||
/**
|
||||
* Deletes all stored settings
|
||||
*
|
||||
* @param string|null $prefix if set only delete settings with given name prefix (e.g. theme.)
|
||||
* @param string|array|Stringable|null $prefix if set, only delete settings with given name prefix (e.g. "theme.")
|
||||
* Versions before 1.15 used the `$prefix` parameter as a full wildcard (`'%pattern%'`) and not actually as a prefix. Use
|
||||
* `$prefix = '%pattern%'` to get the old behaviour. Or use `$parameter = '%suffix'` if you want to match
|
||||
* against the end of the names.
|
||||
*/
|
||||
public function deleteAll($prefix = null)
|
||||
{
|
||||
$query = $this->find();
|
||||
|
||||
if ($prefix !== null) {
|
||||
$query->andWhere(new LikeCondition('name', 'LIKE', $prefix));
|
||||
if (StringHelper::isStringable($prefix)) {
|
||||
if (false === strpos($prefix, "%")) {
|
||||
$prefix .= "%";
|
||||
}
|
||||
} elseif (!is_array($prefix)) {
|
||||
throw new InvalidArgumentTypeException(
|
||||
__METHOD__,
|
||||
[1 => '$prefix'],
|
||||
['string', 'int', 'null', \Stringable::class],
|
||||
$prefix
|
||||
);
|
||||
}
|
||||
|
||||
$query->andWhere(['LIKE', 'name', $prefix, false]);
|
||||
}
|
||||
|
||||
foreach ($query->all() as $setting) {
|
||||
$this->delete($setting->name);
|
||||
}
|
||||
$settings = $query->all();
|
||||
array_walk($settings, static fn($setting, $i, $self) => $self->delete($setting->name), $this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
namespace humhub\libs;
|
||||
|
||||
use Stringable;
|
||||
|
||||
/**
|
||||
* StringHelper
|
||||
*
|
||||
@ -16,11 +18,11 @@ namespace humhub\libs;
|
||||
*/
|
||||
class StringHelper extends \yii\helpers\StringHelper
|
||||
{
|
||||
|
||||
/**
|
||||
* Converts (LDAP) Binary to Ascii GUID
|
||||
*
|
||||
* @param string $object_guid a binary string containing data.
|
||||
*
|
||||
* @return string the guid
|
||||
*/
|
||||
public static function binaryToGuid($object_guid)
|
||||
@ -48,4 +50,62 @@ class StringHelper extends \yii\helpers\StringHelper
|
||||
|
||||
return strtolower($hex_guid_to_guid_str);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param mixed $string String to test, and if $convert is true, to turn into string
|
||||
* @param bool $convert
|
||||
*
|
||||
* @return bool
|
||||
* @since 1.15
|
||||
*/
|
||||
public static function isStringable(&$string, bool $convert = true): bool
|
||||
{
|
||||
switch (getType($string)) {
|
||||
case "string":
|
||||
return true;
|
||||
|
||||
case "bool":
|
||||
case "boolean":
|
||||
if (!$convert) {
|
||||
return true;
|
||||
}
|
||||
$string = (string)(int)$string;
|
||||
return true;
|
||||
|
||||
case "int":
|
||||
case "integer":
|
||||
case "null":
|
||||
if (!$convert) {
|
||||
return true;
|
||||
}
|
||||
$string = (string)$string;
|
||||
return true;
|
||||
|
||||
case "double":
|
||||
case "float":
|
||||
if (!$convert) {
|
||||
return true;
|
||||
}
|
||||
$string = \yii\helpers\StringHelper::floatToString($string);
|
||||
return true;
|
||||
|
||||
case "array":
|
||||
return false;
|
||||
|
||||
case "object":
|
||||
if ($string instanceof Stringable || (is_object($string) && is_callable([$string, '__toString']))) {
|
||||
if (!$convert) {
|
||||
return true;
|
||||
}
|
||||
$string = (string)$string;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
default:
|
||||
// "resource", "NULL", "unknown type", "resource (closed)"
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -132,31 +132,27 @@ class Setting extends SettingActiveRecord
|
||||
*/
|
||||
public static function fixModuleIdAndName($name, $moduleId)
|
||||
{
|
||||
if ($name == 'allowGuestAccess' && $moduleId == 'authentication_internal') {
|
||||
return ['allowGuestAccess', 'user'];
|
||||
} elseif ($name == 'defaultUserGroup' && $moduleId == 'authentication_internal') {
|
||||
return ['auth.allowGuestAccess', 'user'];
|
||||
} elseif ($name == 'systemEmailAddress' && $moduleId == 'mailing') {
|
||||
return ['mailer.systemEmailAddress', 'user'];
|
||||
} elseif ($name == 'systemEmailName' && $moduleId == 'mailing') {
|
||||
return ['mailer.systemEmailName', 'user'];
|
||||
} elseif ($name == 'systemEmailReplyTo' && $moduleId == 'mailing') {
|
||||
return ['mailer.systemEmailReplyTo', 'user'];
|
||||
} elseif ($name == 'enabled' && $moduleId == 'proxy') {
|
||||
return ['proxy.enabled', 'base'];
|
||||
} elseif ($name == 'server' && $moduleId == 'proxy') {
|
||||
return ['proxy.server', 'base'];
|
||||
} elseif ($name == 'port' && $moduleId == 'proxy') {
|
||||
return ['proxy.port', 'base'];
|
||||
} elseif ($name == 'user' && $moduleId == 'proxy') {
|
||||
return ['proxy.user', 'base'];
|
||||
} elseif ($name == 'pass' && $moduleId == 'proxy') {
|
||||
return ['proxy.password', 'base'];
|
||||
} elseif ($name == 'noproxy' && $moduleId == 'proxy') {
|
||||
return ['proxy.noproxy', 'base'];
|
||||
}
|
||||
static $translation = [
|
||||
'authentication_internal' => [
|
||||
'allowGuestAccess' => ['allowGuestAccess', 'user'],
|
||||
'defaultUserGroup' => ['auth.allowGuestAccess', 'user'],
|
||||
],
|
||||
'mailing' => [
|
||||
'systemEmailAddress' => ['mailer.systemEmailAddress', 'user'],
|
||||
'mailing' => ['mailer.systemEmailName', 'user'],
|
||||
'systemEmailReplyTo' => ['mailer.systemEmailReplyTo', 'user'],
|
||||
],
|
||||
'proxy' => [
|
||||
'enabled' => ['proxy.enabled', 'base'],
|
||||
'server' => ['proxy.server', 'base'],
|
||||
'port' => ['proxy.port', 'base'],
|
||||
'user' => ['proxy.user', 'base'],
|
||||
'pass' => ['proxy.password', 'base'],
|
||||
'noproxy' => ['proxy.noproxy', 'base']
|
||||
]
|
||||
];
|
||||
|
||||
return [$name, $moduleId];
|
||||
return $translation[$moduleId][$name] ?? [$name, $moduleId];
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -25,10 +25,10 @@ class ContentContainerSetting extends SettingActiveRecord
|
||||
{
|
||||
|
||||
/** @inheritdoc */
|
||||
protected const CACHE_KEY_FORMAT = 'settings-%s-%d';
|
||||
public const CACHE_KEY_FORMAT = 'settings-%s-%d';
|
||||
|
||||
/** @inheritdoc */
|
||||
protected const CACHE_KEY_FIELDS = ['module_id', 'contentcontainer_id'];
|
||||
public const CACHE_KEY_FIELDS = ['module_id', 'contentcontainer_id'];
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
/**
|
||||
* HumHub
|
||||
* Copyright © 2014 The HumHub Project
|
||||
* Copyright © 2014-2023 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
|
||||
@ -17,4 +17,10 @@
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*/
|
||||
return [];
|
||||
|
||||
return [
|
||||
['name' => 'testSetting1', 'value' => 'Test Setting 1 for User Admin', 'module_id' => 'user', 'contentcontainer_id' => 1 ],
|
||||
['name' => 'testSetting2', 'value' => 'Test Setting 2 for User Admin', 'module_id' => 'user', 'contentcontainer_id' => 1 ],
|
||||
['name' => 'testSetting1', 'value' => 'Test Setting 1 for User User1', 'module_id' => 'user', 'contentcontainer_id' => 2 ],
|
||||
['name' => 'testSetting2', 'value' => 'Test Setting 2 for User User1', 'module_id' => 'user', 'contentcontainer_id' => 2 ],
|
||||
];
|
||||
|
@ -23,4 +23,4 @@ modules:
|
||||
restart: true
|
||||
capabilities:
|
||||
chromeOptions:
|
||||
args: ["--lang=en-US"]
|
||||
args: ["--lang=en-US"]
|
||||
|
@ -1,11 +1,15 @@
|
||||
<?php
|
||||
|
||||
//Initialize Yii
|
||||
use Codeception\Configuration;
|
||||
use Codeception\Util\Autoload;
|
||||
|
||||
defined('YII_DEBUG') or define('YII_DEBUG', true);
|
||||
defined('YII_ENV') or define('YII_ENV', 'test');
|
||||
defined('YII_ENV_TEST') or define('YII_ENV_TEST', true);
|
||||
|
||||
defined('YII_TEST_ENTRY_URL') or define('YII_TEST_ENTRY_URL', parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_PATH));
|
||||
defined('YII_TEST_ENTRY_FILE') or define('YII_TEST_ENTRY_FILE', dirname(dirname(dirname(dirname(__DIR__)))) . '/index-test.php');
|
||||
defined('YII_TEST_ENTRY_URL') or define('YII_TEST_ENTRY_URL', parse_url(Configuration::config()['config']['test_entry_url'], PHP_URL_PATH));
|
||||
defined('YII_TEST_ENTRY_FILE') or define('YII_TEST_ENTRY_FILE', dirname(__DIR__, 4) . '/index-test.php');
|
||||
|
||||
require_once(__DIR__ . '/../../../vendor/autoload.php');
|
||||
require_once(__DIR__ . '/../../../vendor/yiisoft/yii2/Yii.php');
|
||||
@ -13,18 +17,18 @@ require_once(__DIR__ . '/../../../vendor/yiisoft/yii2/Yii.php');
|
||||
$_SERVER['SCRIPT_FILENAME'] = YII_TEST_ENTRY_FILE;
|
||||
$_SERVER['SCRIPT_NAME'] = YII_TEST_ENTRY_URL;
|
||||
|
||||
$_SERVER['SERVER_NAME'] = parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_HOST);
|
||||
$_SERVER['SERVER_PORT'] = parse_url(\Codeception\Configuration::config()['config']['test_entry_url'], PHP_URL_PORT) ? : '80';
|
||||
$_SERVER['SERVER_NAME'] = parse_url(Configuration::config()['config']['test_entry_url'], PHP_URL_HOST);
|
||||
$_SERVER['SERVER_PORT'] = parse_url(Configuration::config()['config']['test_entry_url'], PHP_URL_PORT) ? : '80';
|
||||
|
||||
// Set alias
|
||||
$config = \Codeception\Configuration::config();
|
||||
$config = Configuration::config();
|
||||
|
||||
$config['test_root'] = isset($config['test_root']) ? $config['test_root'] : dirname(__DIR__);
|
||||
$config['humhub_root'] = isset($config['humhub_root']) ? $config['humhub_root'] : realpath(dirname(__DIR__ ). '/../../../');
|
||||
$config['test_root'] = $config['test_root'] ?? dirname(__DIR__);
|
||||
$config['humhub_root'] = $config['humhub_root'] ?? dirname(__DIR__, 4) . '/';
|
||||
|
||||
Yii::setAlias('@tests', $config['test_root']);
|
||||
Yii::setAlias('@env', '@tests/config/env');
|
||||
Yii::setAlias('@modules', dirname(dirname(__DIR__)).'/modules');
|
||||
Yii::setAlias('@modules', dirname(__DIR__, 2) . '/modules');
|
||||
Yii::setAlias('@root', $config['humhub_root']);
|
||||
Yii::setAlias('@humhubTests', $config['humhub_root'] . '/protected/humhub/tests');
|
||||
Yii::setAlias('@humhub', $config['humhub_root'] . '/protected/humhub');
|
||||
@ -32,8 +36,8 @@ Yii::setAlias('@humhub', $config['humhub_root'] . '/protected/humhub');
|
||||
Yii::setAlias('@web-static', '/static');
|
||||
Yii::setAlias('@webroot-static', '@root/static');
|
||||
|
||||
// Load all supporting test classes needed for test execution
|
||||
\Codeception\Util\Autoload::addNamespace('', Yii::getAlias('@humhubTests/codeception/_support'));
|
||||
\Codeception\Util\Autoload::addNamespace('', Yii::getAlias('@tests/codeception/fixtures'));
|
||||
\Codeception\Util\Autoload::addNamespace('', Yii::getAlias('@humhubTests/codeception/fixtures'));
|
||||
\Codeception\Util\Autoload::addNamespace('', Yii::getAlias('@humhubTests/codeception/_pages'));
|
||||
// Load all supporting test classes needed for test execution
|
||||
Autoload::addNamespace('', Yii::getAlias('@humhubTests/codeception/_support'));
|
||||
Autoload::addNamespace('', Yii::getAlias('@tests/codeception/fixtures'));
|
||||
Autoload::addNamespace('', Yii::getAlias('@humhubTests/codeception/fixtures'));
|
||||
Autoload::addNamespace('', Yii::getAlias('@humhubTests/codeception/_pages'));
|
||||
|
@ -1,53 +1,64 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2023 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
/**
|
||||
* This file is executed before the _bootstrap file and loads the humhub test config
|
||||
* test.php by means of the env settings.
|
||||
*/
|
||||
$codeceptConfig = \Codeception\Configuration::config();
|
||||
|
||||
use Codeception\Configuration;
|
||||
|
||||
$codeceptConfig = Configuration::config();
|
||||
|
||||
$testRoot = $codeceptConfig['test_root'];
|
||||
$humhubRoot = $codeceptConfig['humhub_root'];
|
||||
|
||||
// Parse the environment arguments
|
||||
$env = isset($GLOBALS['env']) ? $GLOBALS['env'] : [];
|
||||
$env = $GLOBALS['env'] ?? [];
|
||||
|
||||
// If an environment was set try loading special environment config else load default config
|
||||
if(count($env) > 0) {
|
||||
\Codeception\Configuration::append(['environment' => $env]);
|
||||
if (count($env) > 0) {
|
||||
Configuration::append(['environment' => $env]);
|
||||
|
||||
print_r('Run execution environment: '.$env[0]);
|
||||
|
||||
$envCfgFile = $testRoot.'/config/env/'.$env[0].'/test.php';
|
||||
/** @noinspection ForgottenDebugOutputInspection */
|
||||
print_r('Run execution environment: ' . $env[0]);
|
||||
|
||||
$envCfgFile = $testRoot . '/config/env/' . $env[0] . '/test.php';
|
||||
|
||||
if (file_exists($envCfgFile)) {
|
||||
$cfg = array_merge(require_once($testRoot.'/config/test.php'), require_once($envCfgFile));
|
||||
$cfg = array_merge(require($testRoot . '/config/test.php'), require($envCfgFile));
|
||||
}
|
||||
}
|
||||
|
||||
// If no environment is set we have to load the default config
|
||||
if(!isset($cfg)) {
|
||||
$cfg = require($testRoot.'/config/test.php');
|
||||
if (!isset($cfg)) {
|
||||
$cfg = require($testRoot . '/config/test.php');
|
||||
}
|
||||
|
||||
// We prefer the system enviroment setting over the configuration
|
||||
if($humhubRoot != null) {
|
||||
// We prefer the system environment setting over the configuration
|
||||
if ($humhubRoot) {
|
||||
$cfg['humhub_root'] = $humhubRoot;
|
||||
} else {
|
||||
// If no humhub_root is given we assume to be in /protected/humhub/modules/<module>/tests/codeception directory
|
||||
$cfg['humhub_root'] = ($cfg['humhub_root'] != null) ? $cfg['humhub_root'] : $testRoot . '../../../../';
|
||||
$cfg['humhub_root'] ??= $testRoot . '../../../../';
|
||||
}
|
||||
|
||||
// Set some configurations and overwrite the humhub_root
|
||||
if(isset($cfg['modules'])) {
|
||||
\Codeception\Configuration::append(['humhub_modules' => $cfg['modules']]);
|
||||
if (isset($cfg['modules'])) {
|
||||
Configuration::append(['humhub_modules' => $cfg['modules']]);
|
||||
}
|
||||
|
||||
if(isset($cfg['humhub_root'])) {
|
||||
\Codeception\Configuration::append(['humhub_root' => $cfg['humhub_root']]);
|
||||
if (isset($cfg['humhub_root'])) {
|
||||
Configuration::append(['humhub_root' => $cfg['humhub_root']]);
|
||||
}
|
||||
|
||||
if(isset($cfg['fixtures'])) {
|
||||
\Codeception\Configuration::append(['fixtures' => $cfg['fixtures']]);
|
||||
if (isset($cfg['fixtures'])) {
|
||||
Configuration::append(['fixtures' => $cfg['fixtures']]);
|
||||
}
|
||||
|
||||
return $cfg;
|
||||
|
@ -4,6 +4,7 @@ namespace tests\codeception\_support;
|
||||
|
||||
use Codeception\Module;
|
||||
use humhub\modules\activity\tests\codeception\fixtures\ActivityFixture;
|
||||
use humhub\modules\content\tests\codeception\fixtures\ContentContainerSettingFixture;
|
||||
use humhub\modules\content\tests\codeception\fixtures\ContentFixture;
|
||||
use humhub\modules\file\models\FileHistory;
|
||||
use humhub\modules\file\tests\codeception\fixtures\FileFixture;
|
||||
@ -125,6 +126,7 @@ class DynamicFixtureHelper extends Module
|
||||
'url_oembed' => ['class' => UrlOembedFixture::class],
|
||||
'group_permission' => ['class' => GroupPermissionFixture::class],
|
||||
'settings' => ['class' => SettingFixture::class],
|
||||
'contentcontainer_settings' => ['class' => ContentContainerSettingFixture::class],
|
||||
'space' => [ 'class' => SpaceFixture::class],
|
||||
'space_membership' => [ 'class' => SpaceMembershipFixture::class],
|
||||
'content' => ['class' => ContentFixture::class],
|
||||
|
@ -2,14 +2,30 @@
|
||||
|
||||
namespace tests\codeception\_support;
|
||||
|
||||
use Codeception\Configuration;
|
||||
use Codeception\Exception\ModuleException;
|
||||
use Codeception\Module;
|
||||
use Codeception\Module\Yii2;
|
||||
use humhub\models\UrlOembed;
|
||||
use humhub\modules\activity\tests\codeception\fixtures\ActivityFixture;
|
||||
use humhub\modules\content\tests\codeception\fixtures\ContentContainerFixture;
|
||||
use humhub\modules\content\tests\codeception\fixtures\ContentFixture;
|
||||
use humhub\modules\content\widgets\richtext\converter\RichTextToHtmlConverter;
|
||||
use humhub\modules\content\widgets\richtext\converter\RichTextToMarkdownConverter;
|
||||
use humhub\modules\content\widgets\richtext\converter\RichTextToPlainTextConverter;
|
||||
use humhub\modules\content\widgets\richtext\converter\RichTextToShortTextConverter;
|
||||
use humhub\modules\file\tests\codeception\fixtures\FileFixture;
|
||||
use humhub\modules\file\tests\codeception\fixtures\FileHistoryFixture;
|
||||
use humhub\modules\friendship\tests\codeception\fixtures\FriendshipFixture;
|
||||
use humhub\modules\live\tests\codeception\fixtures\LiveFixture;
|
||||
use humhub\modules\notification\tests\codeception\fixtures\NotificationFixture;
|
||||
use humhub\modules\space\tests\codeception\fixtures\SpaceFixture;
|
||||
use humhub\modules\space\tests\codeception\fixtures\SpaceMembershipFixture;
|
||||
use humhub\modules\user\tests\codeception\fixtures\GroupPermissionFixture;
|
||||
use humhub\modules\user\tests\codeception\fixtures\UserFullFixture;
|
||||
use humhub\tests\codeception\fixtures\SettingFixture;
|
||||
use humhub\tests\codeception\fixtures\UrlOembedFixture;
|
||||
use TypeError;
|
||||
use Yii;
|
||||
use yii\db\ActiveRecord;
|
||||
use Codeception\Test\Unit;
|
||||
@ -20,13 +36,16 @@ use humhub\modules\notification\models\Notification;
|
||||
use humhub\modules\user\components\PermissionManager;
|
||||
use humhub\modules\user\models\User;
|
||||
use humhub\modules\friendship\models\Friendship;
|
||||
use yii\db\Command;
|
||||
use yii\db\Exception;
|
||||
use yii\db\ExpressionInterface;
|
||||
use yii\db\Query;
|
||||
|
||||
/**
|
||||
* @SuppressWarnings(PHPMD)
|
||||
*/
|
||||
class HumHubDbTestCase extends Unit
|
||||
{
|
||||
|
||||
protected $fixtureConfig;
|
||||
|
||||
public $appConfig = '@tests/codeception/config/unit.php';
|
||||
@ -38,7 +57,7 @@ class HumHubDbTestCase extends Unit
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$webRoot = dirname(dirname(__DIR__)) . '/../../..';
|
||||
$webRoot = dirname(__DIR__, 2) . '/../../..';
|
||||
Yii::setAlias('@webroot', realpath($webRoot));
|
||||
$this->initModules();
|
||||
$this->reloadSettings();
|
||||
@ -83,19 +102,17 @@ class HumHubDbTestCase extends Unit
|
||||
*/
|
||||
protected function initModules()
|
||||
{
|
||||
$cfg = \Codeception\Configuration::config();
|
||||
$cfg = Configuration::config();
|
||||
|
||||
if (!empty($cfg['humhub_modules'])) {
|
||||
Yii::$app->moduleManager->enableModules($cfg['humhub_modules']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
public function _fixtures()
|
||||
/* @codingStandardsIgnoreLine PSR2.Methods.MethodDeclaration.Underscore */
|
||||
public function _fixtures(): array
|
||||
{
|
||||
$cfg = \Codeception\Configuration::config();
|
||||
$cfg = Configuration::config();
|
||||
|
||||
if (!$this->fixtureConfig && isset($cfg['fixtures'])) {
|
||||
$this->fixtureConfig = $cfg['fixtures'];
|
||||
@ -116,22 +133,22 @@ class HumHubDbTestCase extends Unit
|
||||
return $result;
|
||||
}
|
||||
|
||||
protected function getDefaultFixtures()
|
||||
protected function getDefaultFixtures(): array
|
||||
{
|
||||
return [
|
||||
'user' => ['class' => UserFullFixture::class],
|
||||
'url_oembed' => ['class' => UrlOembedFixture::class],
|
||||
'group_permission' => ['class' => \humhub\modules\user\tests\codeception\fixtures\GroupPermissionFixture::class],
|
||||
'contentcontainer' => ['class' => \humhub\modules\content\tests\codeception\fixtures\ContentContainerFixture::class],
|
||||
'settings' => ['class' => \humhub\tests\codeception\fixtures\SettingFixture::class],
|
||||
'space' => ['class' => \humhub\modules\space\tests\codeception\fixtures\SpaceFixture::class],
|
||||
'space_membership' => ['class' => \humhub\modules\space\tests\codeception\fixtures\SpaceMembershipFixture::class],
|
||||
'content' => ['class' => \humhub\modules\content\tests\codeception\fixtures\ContentFixture::class],
|
||||
'notification' => ['class' => \humhub\modules\notification\tests\codeception\fixtures\NotificationFixture::class],
|
||||
'file' => ['class' => \humhub\modules\file\tests\codeception\fixtures\FileFixture::class],
|
||||
'file_history' => ['class' => \humhub\modules\file\tests\codeception\fixtures\FileHistoryFixture::class],
|
||||
'activity' => ['class' => \humhub\modules\activity\tests\codeception\fixtures\ActivityFixture::class],
|
||||
'friendship' => ['class' => \humhub\modules\friendship\tests\codeception\fixtures\FriendshipFixture::class],
|
||||
'group_permission' => ['class' => GroupPermissionFixture::class],
|
||||
'contentcontainer' => ['class' => ContentContainerFixture::class],
|
||||
'settings' => ['class' => SettingFixture::class],
|
||||
'space' => ['class' => SpaceFixture::class],
|
||||
'space_membership' => ['class' => SpaceMembershipFixture::class],
|
||||
'content' => ['class' => ContentFixture::class],
|
||||
'notification' => ['class' => NotificationFixture::class],
|
||||
'file' => ['class' => FileFixture::class],
|
||||
'file_history' => ['class' => FileHistoryFixture::class],
|
||||
'activity' => ['class' => ActivityFixture::class],
|
||||
'friendship' => ['class' => FriendshipFixture::class],
|
||||
'live' => [ 'class' => LiveFixture::class]
|
||||
];
|
||||
}
|
||||
@ -143,7 +160,7 @@ class HumHubDbTestCase extends Unit
|
||||
'source_class' => $source->className(),
|
||||
'source_pk' => $source->getPrimaryKey(),
|
||||
]);
|
||||
if(is_string($target_id)) {
|
||||
if (is_string($target_id)) {
|
||||
$msg = $target_id;
|
||||
$target_id = null;
|
||||
}
|
||||
@ -152,7 +169,7 @@ class HumHubDbTestCase extends Unit
|
||||
$notificationQuery->andWhere(['originator_user_id' => $originator_id]);
|
||||
}
|
||||
|
||||
if($target_id != null) {
|
||||
if ($target_id != null) {
|
||||
$notificationQuery->andWhere(['user_id' => $target_id]);
|
||||
}
|
||||
|
||||
@ -167,7 +184,7 @@ class HumHubDbTestCase extends Unit
|
||||
$notificationQuery->andWhere(['originator_user_id' => $originator_id]);
|
||||
}
|
||||
|
||||
if($target_id != null) {
|
||||
if ($target_id != null) {
|
||||
$notificationQuery->andWhere(['user_id' => $target_id]);
|
||||
}
|
||||
|
||||
@ -182,7 +199,7 @@ class HumHubDbTestCase extends Unit
|
||||
$notificationQuery->andWhere(['originator_user_id' => $originator_id]);
|
||||
}
|
||||
|
||||
if($target_id != null) {
|
||||
if ($target_id != null) {
|
||||
$notificationQuery->andWhere(['user_id' => $target_id]);
|
||||
}
|
||||
|
||||
@ -200,10 +217,11 @@ class HumHubDbTestCase extends Unit
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Codeception\Module\Yii2|\Codeception\Module
|
||||
* @throws \Codeception\Exception\ModuleException
|
||||
* @return Yii2|Module
|
||||
* @throws ModuleException
|
||||
*/
|
||||
public function getYiiModule() {
|
||||
public function getYiiModule()
|
||||
{
|
||||
return $this->getModule('Yii2');
|
||||
}
|
||||
|
||||
@ -213,25 +231,28 @@ class HumHubDbTestCase extends Unit
|
||||
*/
|
||||
public function assertMailSent($count = 0)
|
||||
{
|
||||
return $this->getYiiModule()->seeEmailIsSent($count);
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$this->getYiiModule()->seeEmailIsSent($count);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int $count
|
||||
* @throws \Codeception\Exception\ModuleException
|
||||
*
|
||||
* @throws ModuleException
|
||||
* @since 1.3
|
||||
*/
|
||||
public function assertSentEmail($count = 0)
|
||||
public function assertSentEmail(int $count = 0)
|
||||
{
|
||||
return $this->getYiiModule()->seeEmailIsSent($count);
|
||||
$this->getYiiModule()->seeEmailIsSent($count);
|
||||
}
|
||||
|
||||
public function assertEqualsLastEmailTo($to, $strict = true)
|
||||
{
|
||||
if(is_string($to)) {
|
||||
if (is_string($to)) {
|
||||
$to = [$to];
|
||||
}
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$message = $this->getYiiModule()->grabLastSentEmail();
|
||||
$expected = $message->getTo();
|
||||
|
||||
@ -239,22 +260,125 @@ class HumHubDbTestCase extends Unit
|
||||
$this->assertArrayHasKey($email, $expected);
|
||||
}
|
||||
|
||||
if($strict) {
|
||||
$this->assertEquals(count($to), count($expected));
|
||||
if ($strict) {
|
||||
$this->assertCount(count($expected), $to);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function assertEqualsLastEmailSubject($subject)
|
||||
{
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
$message = $this->getYiiModule()->grabLastSentEmail();
|
||||
$this->assertEquals($subject, str_replace(["\n", "\r"], '', $message->getSubject()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|null $expected Number of records expected. Null for any number, but not none
|
||||
* @param string|array|ExpressionInterface $tables
|
||||
* @param string|array|ExpressionInterface|null $condition
|
||||
* @param array|null $params
|
||||
* @param string $message
|
||||
*
|
||||
* @return void
|
||||
* @since 1.15
|
||||
*/
|
||||
public function assertRecordCount(?int $expected, $tables, $condition = null, ?array $params = [], string $message = ''): void
|
||||
{
|
||||
$count = $this->dbCount($tables, $condition, $params ?? []);
|
||||
|
||||
if ($expected === null) {
|
||||
$this->assertGreaterThan(0, $count, $message);
|
||||
} else {
|
||||
$this->assertEquals($expected, $count, $message);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array|ExpressionInterface $tables
|
||||
* @param string|array|ExpressionInterface|null $condition
|
||||
* @param array|null $params
|
||||
* @param string $message
|
||||
*
|
||||
* @return void
|
||||
* @since 1.15
|
||||
*/
|
||||
public function assertRecordExistsAny($tables, $condition = null, ?array $params = [], string $message = 'Record does not exist'): void
|
||||
{
|
||||
$this->assertRecordCount(null, $tables, $condition, $params ?? [], $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array|ExpressionInterface $tables
|
||||
* @param string|array|ExpressionInterface|null $condition
|
||||
* @param array|null $params
|
||||
* @param string $message
|
||||
*
|
||||
* @return void
|
||||
* @since 1.15
|
||||
*/
|
||||
public function assertRecordExists($tables, $condition = null, ?array $params = [], string $message = 'Record does not exist'): void
|
||||
{
|
||||
$this->assertRecordCount(1, $tables, $condition, $params ?? [], $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|array|ExpressionInterface $tables
|
||||
* @param string|array|ExpressionInterface|null $condition
|
||||
* @param array|null $params
|
||||
* @param string $message
|
||||
*
|
||||
* @return void
|
||||
* @since 1.15
|
||||
*/
|
||||
public function assertRecordNotExists($tables, $condition = null, ?array $params = [], string $message = 'Record exists'): void
|
||||
{
|
||||
$this->assertRecordCount(0, $tables, $condition, $params ?? [], $message);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param int|string|null $expected Number of records expected. Null for any number, but not none
|
||||
* @param string $column
|
||||
* @param string|array|ExpressionInterface $tables
|
||||
* @param string|array|ExpressionInterface|null $condition
|
||||
* @param array|null $params
|
||||
* @param string $message
|
||||
*
|
||||
* @return void
|
||||
* @since 1.15
|
||||
*/
|
||||
public function assertRecordValue($expected, string $column, $tables, $condition = null, ?array $params = [], string $message = ''): void
|
||||
{
|
||||
$value = $this->dbQuery($tables, $condition, $params, 1)->select($column)->scalar();
|
||||
$this->assertEquals($expected, $value, $message);
|
||||
}
|
||||
|
||||
public function expectExceptionTypeError(string $calledClass, string $method, int $argumentNumber, string $argumentName, string $expectedType, string $givenTye, string $exceptionClass = TypeError::class): void
|
||||
{
|
||||
$this->expectException($exceptionClass);
|
||||
|
||||
$calledClass = str_replace('\\', '\\\\', $calledClass);
|
||||
$argumentName = ltrim($argumentName, '$');
|
||||
|
||||
$this->expectExceptionMessageRegExp(
|
||||
sprintf(
|
||||
// Php < 8 uses: "Argument n passed to class::method() ..."
|
||||
// PHP > 7 uses: "class::method(): Argument #n ($argument) ..."
|
||||
'@^((Argument %d passed to )?%s::%s\\(\\)(?(2)|: Argument #%d \\(\\$%s\\))) must be of( the)? type %s, %s given, called in /.*@',
|
||||
$argumentNumber,
|
||||
$calledClass,
|
||||
$method,
|
||||
$argumentNumber,
|
||||
$argumentName,
|
||||
$expectedType,
|
||||
$givenTye
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $allow
|
||||
*/
|
||||
public function allowGuestAccess($allow = true)
|
||||
public function allowGuestAccess(bool $allow = true)
|
||||
{
|
||||
Yii::$app
|
||||
->getModule('user')
|
||||
@ -264,7 +388,7 @@ class HumHubDbTestCase extends Unit
|
||||
|
||||
public function setProfileField($field, $value, $user)
|
||||
{
|
||||
if(is_int($user)) {
|
||||
if (is_int($user)) {
|
||||
$user = User::findOne($user);
|
||||
} elseif (is_string($user)) {
|
||||
$user = User::findOne(['username' => $user]);
|
||||
@ -311,7 +435,7 @@ class HumHubDbTestCase extends Unit
|
||||
$contentContainer->permissionManager->clear();
|
||||
}
|
||||
|
||||
public function becomeUser($userName)
|
||||
public function becomeUser($userName): ?User
|
||||
{
|
||||
$user = User::findOne(['username' => $userName]);
|
||||
Yii::$app->user->switchIdentity($user);
|
||||
@ -320,7 +444,104 @@ class HumHubDbTestCase extends Unit
|
||||
|
||||
public function logout()
|
||||
{
|
||||
Yii::$app->user->logout(true);
|
||||
Yii::$app->user->logout();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see \yii\db\Connection::createCommand()
|
||||
* @since 1.15
|
||||
*/
|
||||
public function dbCommand($sql = null, $params = []): Command
|
||||
{
|
||||
return Yii::$app->getDb()->createCommand($sql, $params);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Command $cmd
|
||||
* @param bool $execute
|
||||
*
|
||||
* @return Command
|
||||
* @throws Exception
|
||||
*/
|
||||
protected function dbCommandExecute(Command $cmd, bool $execute = true): Command
|
||||
{
|
||||
if ($execute) {
|
||||
$cmd->execute();
|
||||
}
|
||||
|
||||
return $cmd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Query
|
||||
* @since 1.15
|
||||
*/
|
||||
public function dbQuery($tables, $condition, $params = [], $limit = 10): Query
|
||||
{
|
||||
return (new Query())
|
||||
->from($tables)
|
||||
->where($condition, $params)
|
||||
->limit($limit);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Command::insert
|
||||
* @since 1.15
|
||||
*/
|
||||
public function dbInsert($table, $columns, bool $execute = true): Command
|
||||
{
|
||||
return $this->dbCommandExecute($this->dbCommand()->insert($table, $columns), $execute);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Command::update
|
||||
* @since 1.15
|
||||
*/
|
||||
public function dbUpdate($table, $columns, $condition = '', $params = [], bool $execute = true): Command
|
||||
{
|
||||
return $this->dbCommandExecute($this->dbCommand()->update($table, $columns, $condition, $params), $execute);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Command::upsert
|
||||
* @since 1.15
|
||||
*/
|
||||
public function dbUpsert($table, $insertColumns, $updateColumns = true, $params = [], bool $execute = true): Command
|
||||
{
|
||||
return $this->dbCommandExecute($this->dbCommand()->upsert($table, $insertColumns, $updateColumns, $params), $execute);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Command::delete()
|
||||
* @since 1.15
|
||||
*/
|
||||
public function dbDelete($table, $condition = '', $params = [], bool $execute = true): Command
|
||||
{
|
||||
return $this->dbCommandExecute($this->dbCommand()->delete($table, $condition, $params), $execute);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Query::select
|
||||
* @see Query::from
|
||||
* @see Query::where
|
||||
* @see \yii\db\QueryTrait::limit()
|
||||
* @since 1.15
|
||||
*/
|
||||
public function dbSelect($tables, $columns, $condition = '', $params = [], $limit = 10, $selectOption = null): array
|
||||
{
|
||||
return $this->dbQuery($tables, $condition, $params, $limit)
|
||||
->select($columns, $selectOption)
|
||||
->all();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Command::delete()
|
||||
* @since 1.15
|
||||
*/
|
||||
public function dbCount($tables, $condition = '', $params = [])
|
||||
{
|
||||
return $this->dbQuery($tables, $condition, $params)
|
||||
->select("count(*)")
|
||||
->scalar();
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,14 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2023 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace tests\codeception\_support;
|
||||
|
||||
use Codeception\Exception\ConfigurationException;
|
||||
use Yii;
|
||||
|
||||
/**
|
||||
@ -13,7 +20,7 @@ class HumHubTestConfiguration
|
||||
* This function is used for retrieving the humhub configuration for
|
||||
* a given test suite by merging default configuration with the test configuration and
|
||||
* environment configuration of the user.
|
||||
*
|
||||
*
|
||||
* @param type $suite
|
||||
* @return type
|
||||
*/
|
||||
@ -22,50 +29,51 @@ class HumHubTestConfiguration
|
||||
$config = self::initConfig($suite);
|
||||
return self::mergeWithEnvironmentConfig($config, $suite);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the configuration for the given suite by merging
|
||||
*
|
||||
*
|
||||
* @humhubTests/codeception/config/<suite>.php -> Default config for this suite
|
||||
* @tests/config/common.php -> Common config of the current test module
|
||||
* @test/config/<suite>.php -> Suite config of the current test module
|
||||
*
|
||||
*
|
||||
* @param type $suite the given suite e.g acceptance/functional/unit
|
||||
* @return type merged config
|
||||
* @return array merged config
|
||||
*/
|
||||
private static function initConfig($suite)
|
||||
private static function initConfig($suite): array
|
||||
{
|
||||
return \yii\helpers\ArrayHelper::merge(
|
||||
// Default Test Config
|
||||
require(Yii::getAlias('@humhubTests/codeception/config/'.$suite.'.php')),
|
||||
require(Yii::getAlias('@humhubTests/codeception/config/' . $suite . '.php')),
|
||||
// User Overwrite Common Config
|
||||
require(Yii::getAlias('@tests/config/common.php')),
|
||||
// User Overwrite Suite Config
|
||||
require(Yii::getAlias('@tests/config/'.$suite.'.php'))
|
||||
require(Yii::getAlias('@tests/config/' . $suite . '.php'))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Merges environmental configuration if existing.
|
||||
* By running "codecept run functional --env myEnvironment" you can choose the execution environment
|
||||
* and overwrite the default configuration in your @tests/config/env/myEnvironment directory.
|
||||
*
|
||||
*
|
||||
* @param type $result
|
||||
* @param type $cfg
|
||||
* @param type $suite
|
||||
*
|
||||
* @return type
|
||||
* @throws ConfigurationException
|
||||
*/
|
||||
private static function mergeWithEnvironmentConfig($result, $suite)
|
||||
{
|
||||
$cfg = \Codeception\Configuration::config();
|
||||
|
||||
|
||||
// If a environment was set we use the first environment as execution environment and try including a environment specific cfg
|
||||
if (isset($cfg['environment'])) {
|
||||
|
||||
$env = $cfg['environment'][0][0];
|
||||
$envCfgCommonFile = Yii::getAlias('@env/'. $env .'/common.php');
|
||||
$envCfgFile = Yii::getAlias('@env/'. $env .'/'.$suite. '.php');
|
||||
|
||||
$envCfgCommonFile = Yii::getAlias('@env/' . $env . '/common.php');
|
||||
$envCfgFile = Yii::getAlias('@env/' . $env . '/' . $suite . '.php');
|
||||
|
||||
//Merge with common environment config
|
||||
if (file_exists($envCfgCommonFile)) {
|
||||
$result = \yii\helpers\ArrayHelper::merge(
|
||||
@ -74,7 +82,7 @@ class HumHubTestConfiguration
|
||||
require($envCfgCommonFile)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
//Merge with suite envornment config
|
||||
if (file_exists($envCfgFile)) {
|
||||
$result = \yii\helpers\ArrayHelper::merge(
|
||||
@ -84,7 +92,7 @@ class HumHubTestConfiguration
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ $consoleConfig = [
|
||||
]
|
||||
];
|
||||
|
||||
$config = yii\helpers\ArrayHelper::merge(
|
||||
$config = yii\helpers\ArrayHelper::merge(
|
||||
// Common HumHub Config
|
||||
require(YII_APP_BASE_PATH . '/humhub/config/common.php'),
|
||||
// Console HumHub Config
|
||||
|
@ -24,7 +24,7 @@ $testConfig = [
|
||||
],
|
||||
'enablePjax' => true
|
||||
],
|
||||
|
||||
|
||||
];
|
||||
|
||||
defined('YII_APP_BASE_PATH') or define('YII_APP_BASE_PATH', dirname(dirname(dirname(dirname(__DIR__)))));
|
||||
|
@ -1,4 +1,11 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2023 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
return [
|
||||
['name' => 'name', 'value' => 'HumHub', 'module_id' => 'base'],
|
||||
['name' => 'baseUrl', 'value' => 'http://localhost:8080', 'module_id' => 'base'],
|
||||
@ -67,4 +74,6 @@ return [
|
||||
['name' => 'defaultLanguage', 'value' => 'en-US', 'module_id' => 'base'],
|
||||
['name' => 'maintenanceMode', 'value' => '0', 'module_id' => 'base'],
|
||||
['name' => 'enableProfilePermissions', 'value' => '1', 'module_id' => 'user'],
|
||||
['name' => 'testSetting', 'value' => 'Test Setting for Base', 'module_id' => 'base' ],
|
||||
['name' => 'testSetting0', 'value' => 'Test Setting 0 for Base', 'module_id' => 'base', ],
|
||||
];
|
||||
|
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2023 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\tests\codeception\unit\components;
|
||||
|
||||
use Codeception\Test\Unit;
|
||||
use humhub\libs\BaseSettingsManager;
|
||||
use tests\codeception\_support\HumHubDbTestCase;
|
||||
|
||||
class BaseSettingsManagerTest extends HumHubDbTestCase
|
||||
{
|
||||
public function testIsDatabaseInstalled()
|
||||
{
|
||||
$this->assertTrue(BaseSettingsManager::isDatabaseInstalled());
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2023 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\tests\codeception\unit\components;
|
||||
|
||||
use humhub\components\SettingActiveRecord;
|
||||
use humhub\models\Setting;
|
||||
use tests\codeception\_support\HumHubDbTestCase;
|
||||
use yii\base\InvalidCallException;
|
||||
|
||||
class SettingActiveRecordTest extends HumHubDbTestCase
|
||||
{
|
||||
public function testGetCacheKeyFormat()
|
||||
{
|
||||
$this->assertEquals('settings-%s', SettingActiveRecord::CACHE_KEY_FORMAT, "Cache key format changed!");
|
||||
}
|
||||
|
||||
public function testGetCacheKeyFields()
|
||||
{
|
||||
$this->assertEquals(['module_id'], SettingActiveRecord::CACHE_KEY_FIELDS, "Cache key format changed!");
|
||||
}
|
||||
|
||||
public function testGetCacheKey()
|
||||
{
|
||||
$cacheKey = Setting::getCacheKey('test');
|
||||
$this->assertEquals('settings-test', $cacheKey, "Cache key malformed!");
|
||||
|
||||
$cacheKey = Setting::getCacheKey('test', 'more');
|
||||
$this->assertEquals('settings-test', $cacheKey, "Cache key malformed!");
|
||||
}
|
||||
|
||||
public function testDeleteAll()
|
||||
{
|
||||
$this->expectException(InvalidCallException::class);
|
||||
$this->expectExceptionMessageRegExp(sprintf('@%s@', str_replace('\\', '\\\\', SettingActiveRecord::class)));
|
||||
|
||||
SettingActiveRecord::deleteAll();
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2023 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\tests\codeception\unit\components;
|
||||
|
||||
use humhub\components\SettingsManager;
|
||||
|
||||
class SettingsManagerMock extends SettingsManager
|
||||
{
|
||||
public bool $usedFind = false;
|
||||
|
||||
protected function find()
|
||||
{
|
||||
$this->usedFind = true;
|
||||
|
||||
return parent::find();
|
||||
}
|
||||
|
||||
public function getCacheKey(): string
|
||||
{
|
||||
return parent::getCacheKey();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return bool
|
||||
*/
|
||||
public function didAccessDB(): bool
|
||||
{
|
||||
$read = $this->usedFind;
|
||||
$this->usedFind = false;
|
||||
return $read;
|
||||
}
|
||||
|
||||
public function invalidateCache()
|
||||
{
|
||||
parent::invalidateCache();
|
||||
}
|
||||
}
|
@ -0,0 +1,372 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2023 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
/** @noinspection MissedFieldInspection */
|
||||
|
||||
namespace humhub\tests\codeception\unit\components;
|
||||
|
||||
use humhub\components\SettingsManager;
|
||||
use humhub\libs\BaseSettingsManager;
|
||||
use humhub\models\Setting;
|
||||
use humhub\modules\content\components\ContentContainerSettingsManager;
|
||||
use humhub\modules\space\models\Space;
|
||||
use humhub\modules\user\models\User;
|
||||
use tests\codeception\_support\HumHubDbTestCase;
|
||||
use Yii;
|
||||
use yii\base\InvalidArgumentException;
|
||||
use yii\base\InvalidConfigException;
|
||||
use yii\caching\ArrayCache;
|
||||
use yii\caching\DummyCache;
|
||||
use yii\helpers\ArrayHelper;
|
||||
|
||||
use function PHPUnit\Framework\assertInstanceOf;
|
||||
|
||||
class SettingsManagerTest extends HumHubDbTestCase
|
||||
{
|
||||
protected $fixtureConfig = ['default'];
|
||||
|
||||
public function testCreateWithoutModuleId()
|
||||
{
|
||||
$this->expectException(InvalidConfigException::class);
|
||||
$this->expectExceptionMessage('Module id not set!');
|
||||
|
||||
new SettingsManager();
|
||||
}
|
||||
|
||||
public function testCreateWithEmptyModuleId()
|
||||
{
|
||||
$this->expectException(InvalidConfigException::class);
|
||||
$this->expectExceptionMessage('Empty module id!');
|
||||
|
||||
$this->s = new SettingsManager(['moduleId' => '']);
|
||||
}
|
||||
|
||||
public function testCreateForBaseModule()
|
||||
{
|
||||
$module = 'base';
|
||||
$sm = new SettingsManager(['moduleId' => $module]);
|
||||
|
||||
$this->assertInstanceOf(SettingsManager::class, $sm);
|
||||
}
|
||||
|
||||
public function testCreateForNonExistentModule()
|
||||
{
|
||||
$sm = new SettingsManager(['moduleId' => '_']);
|
||||
|
||||
$this->assertInstanceOf(SettingsManager::class, $sm);
|
||||
}
|
||||
|
||||
public function testGetValuesForBaseModule()
|
||||
{
|
||||
$module = 'base';
|
||||
$sm = new SettingsManager(['moduleId' => $module]);
|
||||
|
||||
$value = $sm->get('testSetting');
|
||||
$this->assertEquals('Test Setting for Base', $value);
|
||||
|
||||
$value = $sm->get('testSetting_');
|
||||
$this->assertNull($value);
|
||||
}
|
||||
|
||||
public function testSpace()
|
||||
{
|
||||
$module = 'base';
|
||||
$sm = new SettingsManager(['moduleId' => $module]);
|
||||
|
||||
$smSpace = $sm->space();
|
||||
$this->assertNull($smSpace, "No Space Settings Manager should have been returned");
|
||||
|
||||
$space = Space::findOne(['id' => 1]);
|
||||
$this->assertInstanceOf(Space::class, $space);
|
||||
|
||||
$smSpace = $sm->space($space);
|
||||
$this->assertInstanceOf(
|
||||
ContentContainerSettingsManager::class,
|
||||
$smSpace,
|
||||
"No Space Settings Manager was returned"
|
||||
);
|
||||
$this->assertEquals($module, $smSpace->moduleId);
|
||||
$this->assertEquals($space, $smSpace->contentContainer);
|
||||
}
|
||||
|
||||
public function testUser()
|
||||
{
|
||||
$module = 'base';
|
||||
$sm = new SettingsManager(['moduleId' => $module]);
|
||||
|
||||
$smUser = $sm->user();
|
||||
$this->assertNull($smUser, "No User Settings Manager should have been returned");
|
||||
|
||||
$user = $this->becomeUser('User2');
|
||||
|
||||
$smUser = $sm->user();
|
||||
$this->assertInstanceOf(
|
||||
ContentContainerSettingsManager::class,
|
||||
$smUser,
|
||||
"No User Settings Manager was returned"
|
||||
);
|
||||
$this->assertEquals($module, $smUser->moduleId);
|
||||
$this->assertEquals($user, $smUser->contentContainer);
|
||||
|
||||
$user = User::findOne(['id' => 2]);
|
||||
$this->assertInstanceOf(User::class, $user);
|
||||
|
||||
$smUser = $sm->user($user);
|
||||
$this->assertInstanceOf(
|
||||
ContentContainerSettingsManager::class,
|
||||
$smUser,
|
||||
"No User Settings Manager was returned"
|
||||
);
|
||||
$this->assertEquals($module, $smUser->moduleId);
|
||||
$this->assertEquals($user, $smUser->contentContainer);
|
||||
}
|
||||
|
||||
public function testSettingValues()
|
||||
{
|
||||
$module = 'base';
|
||||
$table = Setting::tableName();
|
||||
$sm = new SettingsManager(['moduleId' => $module]);
|
||||
|
||||
$this->assertEquals('Test Setting for Base', $sm->get('testSetting'));
|
||||
|
||||
$setting = 'testSetting';
|
||||
$value = 'Hello World';
|
||||
|
||||
$sm->set($setting, $value);
|
||||
$this->assertRecordExists($table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertRecordValue($value, 'value', $table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertEquals($value, $sm->get($setting));
|
||||
|
||||
$setting = 'testSetting_';
|
||||
$value = 'Brave New World';
|
||||
|
||||
$this->assertRecordNotExists($table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertNull($sm->get($setting));
|
||||
|
||||
$sm->set($setting, $value);
|
||||
$this->assertRecordExists($table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertRecordValue($value, 'value', $table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertEquals($value, $sm->get($setting));
|
||||
|
||||
$this->expectExceptionTypeError(BaseSettingsManager::class, 'set', 1, '$name', 'string', 'null');
|
||||
$sm->set(null, "NULL");
|
||||
|
||||
$this->expectException(InvalidArgumentException::class);
|
||||
$this->expectExceptionMessageRegExp('@Argument #1 \\(\\$name\\) passed to .* may not be an empty string!@');
|
||||
$sm->set('', "null-length string");
|
||||
|
||||
$setting = ' ';
|
||||
$value = 'just a space';
|
||||
|
||||
$sm->set($setting, $value);
|
||||
$this->assertRecordExists($table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertRecordValue($value, 'value', $table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertEquals($value, $sm->get($setting));
|
||||
}
|
||||
|
||||
public function testSerialized()
|
||||
{
|
||||
$module = 'base';
|
||||
$table = Setting::tableName();
|
||||
$sm = new SettingsManager(['moduleId' => $module]);
|
||||
|
||||
$setting = 'testJson';
|
||||
$this->assertRecordNotExists($table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertNull($sm->getSerialized($setting), "Setting should not exist");
|
||||
|
||||
$tests = [
|
||||
'5' => 5,
|
||||
'"5"' => "5",
|
||||
'5.5' => 5.5,
|
||||
'"simple text"' => 'simple text',
|
||||
'null' => null,
|
||||
'[]' => [],
|
||||
'{}' => (object)[],
|
||||
'[null,"simple text","text with \"quotes\"",5]' => [null, 'simple text', 'text with "quotes"', 5],
|
||||
'{"0":null,"x":"simple text"}' => [null, 'x' => 'simple text'],
|
||||
'{"x":null,"y":"simple text"}' => (object)['x' => null, 'y' => 'simple text'],
|
||||
];
|
||||
|
||||
array_walk($tests, function ($value, $json) use ($setting, $sm, $table, $module) {
|
||||
$sm->setSerialized($setting, $value);
|
||||
$this->assertRecordExists($table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertRecordValue($json, 'value', $table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertEquals($json, $sm->get($setting));
|
||||
|
||||
if (is_object($value) || is_array($value) && ArrayHelper::isAssociative($value)) {
|
||||
$object = (object)$value;
|
||||
$this->assertEquals($object, $sm->getSerialized($setting, null, false), "testing json: $json");
|
||||
$value = (array)$value;
|
||||
}
|
||||
$this->assertEquals($value, $sm->getSerialized($setting), "testing json: $json");
|
||||
});
|
||||
}
|
||||
|
||||
public function testDelete()
|
||||
{
|
||||
$module = 'base';
|
||||
$table = Setting::tableName();
|
||||
$sm = new SettingsManager(['moduleId' => $module]);
|
||||
|
||||
// delete by null value
|
||||
$setting = 'testSetting';
|
||||
$this->assertNotNull($sm->get($setting));
|
||||
$sm->set($setting, null);
|
||||
$this->assertNull($sm->get($setting));
|
||||
|
||||
// delete by delete()
|
||||
$setting = 'testSetting0';
|
||||
$this->assertRecordExists($table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertNotNull($sm->get($setting));
|
||||
$sm->delete($setting);
|
||||
$this->assertRecordNotExists($table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertNull($sm->get($setting));
|
||||
}
|
||||
|
||||
public function testDeleteAll()
|
||||
{
|
||||
$module = 'base';
|
||||
$table = Setting::tableName();
|
||||
$sm = new SettingsManager(['moduleId' => $module]);
|
||||
|
||||
$setting = 'testSetting';
|
||||
$setting1 = 'testSetting_1';
|
||||
$setting2 = 'testSetting_2';
|
||||
|
||||
$sm->set($setting1, 'something');
|
||||
$sm->set($setting2, 'something');
|
||||
|
||||
$this->assertNotNull($sm->get($setting), "testSetting should not found");
|
||||
$this->assertNotNull($sm->get($setting1), "testSetting_1 was not created");
|
||||
$this->assertNotNull($sm->get($setting2), "testSetting_1 was not created");
|
||||
$this->assertRecordExists($table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertRecordExists($table, ['name' => $setting1, 'module_id' => $module]);
|
||||
$this->assertRecordExists($table, ['name' => $setting2, 'module_id' => $module]);
|
||||
|
||||
$sm->deleteAll('Setting_');
|
||||
|
||||
$this->assertNotNull($sm->get($setting), "testSetting should not have been deleted");
|
||||
$this->assertNotNull($sm->get($setting1), "testSetting_1 should not have been deleted");
|
||||
$this->assertNotNull($sm->get($setting2), "testSetting_2 should not have been deleted");
|
||||
$this->assertRecordExists($table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertRecordExists($table, ['name' => $setting1, 'module_id' => $module]);
|
||||
$this->assertRecordExists($table, ['name' => $setting2, 'module_id' => $module]);
|
||||
|
||||
$sm->deleteAll('testSetting_');
|
||||
|
||||
$this->assertNotNull($sm->get($setting), "testSetting should not have been deleted");
|
||||
$this->assertNull($sm->get($setting1), "testSetting_1 should have been deleted");
|
||||
$this->assertNull($sm->get($setting2), "testSetting_2 should have been deleted");
|
||||
$this->assertRecordExists($table, ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertRecordNotExists($table, ['name' => $setting1, 'module_id' => $module]);
|
||||
$this->assertRecordNotExists($table, ['name' => $setting2, 'module_id' => $module]);
|
||||
|
||||
$sm->deleteAll('%Setting%');
|
||||
|
||||
$this->assertNull($sm->get($setting), "testSetting should not have been deleted");
|
||||
$this->assertRecordNotExists($table, ['name' => $setting, 'module_id' => $module]);
|
||||
|
||||
$this->assertRecordExistsAny($table, ['module_id' => $module]);
|
||||
$sm->deleteAll();
|
||||
$this->assertRecordNotExists($table, ['module_id' => $module]);
|
||||
}
|
||||
|
||||
public function testGetCached()
|
||||
{
|
||||
$module = 'base';
|
||||
$table = Setting::tableName();
|
||||
|
||||
// make sure, cache is disabled
|
||||
|
||||
$cache = Yii::$app->cache;
|
||||
|
||||
if (!$cache instanceof DummyCache) {
|
||||
Yii::$app->set('cache', new DummyCache());
|
||||
}
|
||||
|
||||
assertInstanceOf(DummyCache::class, $cache = Yii::$app->cache);
|
||||
|
||||
// No Cache
|
||||
|
||||
// initialize and load data from database
|
||||
$sm = new SettingsManagerMock(['moduleId' => $module]);
|
||||
$this->assertTrue($sm->didAccessDB());
|
||||
|
||||
// do it again. If there is a cache, then the database is not used. Since there is no cache, it is used again
|
||||
$sm = new SettingsManagerMock(['moduleId' => $module]);
|
||||
$this->assertTrue($sm->didAccessDB());
|
||||
|
||||
// Enable Cache
|
||||
Yii::$app->set('cache', new ArrayCache());
|
||||
assertInstanceOf(ArrayCache::class, $cache = Yii::$app->cache);
|
||||
|
||||
// Enabled Cache
|
||||
|
||||
// initialize and load data from database
|
||||
$sm = new SettingsManagerMock(['moduleId' => $module]);
|
||||
$this->assertTrue($sm->didAccessDB());
|
||||
|
||||
// check if cache is saved
|
||||
$key = $sm->getCacheKey();
|
||||
$this->assertTrue($cache->exists($key));
|
||||
|
||||
// do it again. If there is a cache, then the database is not used. Since there is no cache, it is used again
|
||||
$sm = new SettingsManagerMock(['moduleId' => $module]);
|
||||
$this->assertFalse($sm->didAccessDB());
|
||||
|
||||
$key = $sm->getCacheKey();
|
||||
$this->assertTrue($cache->exists($key));
|
||||
|
||||
$setting = 'testSetting';
|
||||
|
||||
// reading a value should not access the db
|
||||
$this->assertNotNull($sm->get($setting));
|
||||
$this->assertFalse($sm->didAccessDB());
|
||||
|
||||
// however, writing a value should both
|
||||
$value = 'some other value';
|
||||
$sm->set($setting, $value);
|
||||
// ... access the db
|
||||
$this->assertTrue($sm->didAccessDB());
|
||||
// ... and clear the cache
|
||||
$this->assertFalse($cache->exists($key));
|
||||
// DB should be updated, too
|
||||
$this->assertRecordValue($value, 'value', $table, ['name' => $setting, 'module_id' => $module]);
|
||||
|
||||
// next read should still
|
||||
$this->assertEquals($value, $sm->get($setting));
|
||||
// ... not access db
|
||||
$this->assertFalse($sm->didAccessDB());
|
||||
// ... or create the cache
|
||||
$this->assertFalse($cache->exists($key));
|
||||
|
||||
// changing the value behind the scenes
|
||||
$value2 = 'third value';
|
||||
$this->dbUpdate($table, ['value' => $value2], ['name' => $setting, 'module_id' => $module]);
|
||||
$this->assertRecordValue($value2, 'value', $table, ['name' => $setting, 'module_id' => $module]);
|
||||
|
||||
// getting the value now should still show tho "old" value
|
||||
$this->assertEquals($value, $sm->get($setting));
|
||||
|
||||
// reloading the settings should
|
||||
$sm->reload();
|
||||
// ... access the db
|
||||
$this->assertTrue($sm->didAccessDB());
|
||||
// ... and re-build the cache
|
||||
$this->assertTrue($cache->exists($key));
|
||||
// ... and show the updated value
|
||||
$this->assertEquals($value2, $sm->get($setting));
|
||||
|
||||
// invalidating the cache
|
||||
$sm->invalidateCache();
|
||||
// ... not access db
|
||||
$this->assertFalse($sm->didAccessDB());
|
||||
// ... but clear the cache
|
||||
$this->assertFalse($cache->exists($key));
|
||||
}
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @link https://www.humhub.org/
|
||||
* @copyright Copyright (c) 2023 HumHub GmbH & Co. KG
|
||||
* @license https://www.humhub.com/licences
|
||||
*/
|
||||
|
||||
namespace humhub\tests\codeception\unit\models;
|
||||
|
||||
use humhub\models\Setting;
|
||||
use humhub\tests\codeception\unit\components\SettingActiveRecordTest;
|
||||
use yii\base\Exception;
|
||||
|
||||
class SettingTest extends SettingActiveRecordTest
|
||||
{
|
||||
protected $fixtureConfig = ['default'];
|
||||
|
||||
public function testGetCacheKeyFormat()
|
||||
{
|
||||
/** @noinspection PhpClassConstantAccessedViaChildClassInspection */
|
||||
$this->assertEquals('settings-%s', Setting::CACHE_KEY_FORMAT, "Cache key format changed!");
|
||||
}
|
||||
|
||||
public function testGetCacheKeyFields()
|
||||
{
|
||||
/** @noinspection PhpClassConstantAccessedViaChildClassInspection */
|
||||
$this->assertEquals(['module_id'], Setting::CACHE_KEY_FIELDS, "Cache key format changed!");
|
||||
}
|
||||
|
||||
public function testDeleteAll()
|
||||
{
|
||||
$settingBefore = Setting::findAll(['module_id' => 'base', 'name' => 'testSetting']);
|
||||
$this->assertNotEmpty($settingBefore, "Setting 'testSetting' for 'base' not found.");
|
||||
|
||||
Setting::deleteAll(['module_id' => 'base', 'name' => 'testSetting']);
|
||||
|
||||
$settingAfter = Setting::findAll(['module_id' => 'base', 'name' => 'testSetting']);
|
||||
$this->assertCount(0, $settingAfter, "Setting 'testSetting' for 'base' was not deleted.");
|
||||
}
|
||||
|
||||
public function testDeprecatedFixModuleIdAndName()
|
||||
{
|
||||
$this->assertEquals(['foo', 'bar'], Setting::fixModuleIdAndName('foo', 'bar'), "Translation messed things up!");
|
||||
|
||||
$this->assertEquals(
|
||||
['allowGuestAccess', 'user'],
|
||||
Setting::fixModuleIdAndName('allowGuestAccess', 'authentication_internal'),
|
||||
"Translation messed things up!"
|
||||
);
|
||||
}
|
||||
|
||||
public function testDeprecatedGetValidSetting()
|
||||
{
|
||||
$this->assertEquals('Test Setting for Base', Setting::get('testSetting', 'base'), "Invalid value returned!");
|
||||
}
|
||||
|
||||
public function testDeprecatedGetSettingFromInvalidModule()
|
||||
{
|
||||
$this->expectException(Exception::class);
|
||||
$this->expectExceptionMessage('Could not find module: this module does not exist');
|
||||
|
||||
Setting::get('testSetting', 'this module does not exist');
|
||||
}
|
||||
|
||||
public function testDeprecatedGetInvalidSetting()
|
||||
{
|
||||
$this->assertNull(Setting::get('testSetting_', 'base'), "Invalid value returned!");
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user