diff --git a/.gitignore b/.gitignore
index 60ad359..5d58775 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,5 @@ node_modules/
vendor/
composer.lock
package-lock.json
+
+.phpunit.result.cache
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 34a6269..f36a452 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,11 @@
Yii2 multiple input change log
==============================
+3.0.0 (in development)
+=======================
+- rename ValuePreparer to ValueResolver
+
+
2.27.0 (in development)
=======================
diff --git a/composer.json b/composer.json
index bd75afd..8e678d0 100644
--- a/composer.json
+++ b/composer.json
@@ -22,11 +22,11 @@
}
],
"require": {
- "php": ">=5.4.0",
+ "php": ">=7.4",
"yiisoft/yii2": ">=2.0.38"
},
"require-dev": {
- "phpunit/phpunit": "5.7.*"
+ "phpunit/phpunit": "9.*"
},
"autoload": {
"psr-4": {
@@ -34,5 +34,11 @@
"unclead\\multipleinput\\": "src/",
"unclead\\multipleinput\\tests\\": "tests/"
}
- }
+ },
+ "repositories": [
+ {
+ "type": "composer",
+ "url": "https://asset-packagist.org"
+ }
+ ]
}
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
index fd3fa65..28136ee 100644
--- a/phpunit.xml.dist
+++ b/phpunit.xml.dist
@@ -1,22 +1,9 @@
-
-
-
- ./tests
- ./vendor
-
-
-
-
- ./tests/unit/
-
-
-
-
-
-
\ No newline at end of file
+
+
+
+ ./tests/unit/
+
+
+
+
diff --git a/src/MultipleInput.php b/src/MultipleInput.php
index dcad5eb..0e18cb3 100644
--- a/src/MultipleInput.php
+++ b/src/MultipleInput.php
@@ -222,6 +222,10 @@ class MultipleInput extends InputWidget
*/
public function init()
{
+ if (count($this->columns) === 0) {
+ throw new InvalidConfigException('You must specify at least one column');
+ }
+
if ($this->form !== null && !$this->form instanceof ActiveForm) {
throw new InvalidConfigException('Property "form" must be an instance of yii\widgets\ActiveForm');
}
@@ -229,8 +233,6 @@ public function init()
if ($this->showGeneralError && $this->field === null) {
$this->showGeneralError = false;
}
-
- $this->guessColumns();
$this->initData();
parent::init();
@@ -269,25 +271,6 @@ protected function initData()
}
}
- /**
- * This function tries to guess the columns to show from the given data
- * if [[columns]] are not explicitly specified.
- */
- protected function guessColumns()
- {
- if (empty($this->columns)) {
- $column = [
- 'name' => $this->hasModel() ? $this->attribute : $this->name,
- 'type' => MultipleInputColumn::TYPE_TEXT_INPUT
- ];
-
- if ($this->enableGuessTitle && $this->hasModel()) {
- $column['title'] = $this->model->getAttributeLabel($this->attribute);
- }
- $this->columns[] = $column;
- }
- }
-
/**
* Run widget.
*/
diff --git a/src/TabularInput.php b/src/TabularInput.php
index 95e2f89..7d735a6 100644
--- a/src/TabularInput.php
+++ b/src/TabularInput.php
@@ -211,6 +211,10 @@ class TabularInput extends Widget
*/
public function init()
{
+ if (count($this->columns) === 0) {
+ throw new InvalidConfigException('You must specify at least one column');
+ }
+
if (empty($this->models) && !$this->modelClass) {
throw new InvalidConfigException('You must at least specify "models" or "modelClass"');
}
diff --git a/src/components/BaseColumn.php b/src/components/BaseColumn.php
index d4a9928..6e385d5 100644
--- a/src/components/BaseColumn.php
+++ b/src/components/BaseColumn.php
@@ -232,25 +232,25 @@ public function isHiddenInput()
/**
* Prepares the value of column.
+ *
* @param array $contextParams the params who passed to closure:
* string $id the id of input element
* string $name the name of input element
- * string $indexPlaceholder The index placeholder of multiple input. The {$indexPlaceholder} template will be replace by $index
+ * string $indexPlaceholder The index placeholder of multiple input. The {$indexPlaceholder} template will be replaced by $index
* int $index The index of multiple input
* int $columnIndex The index of current model attributes
+ *
* @return mixed
*/
- protected function prepareValue($contextParams = [])
+ protected function resolveValue(array $contextParams = [])
{
$data = $this->getModel();
if ($this->value instanceof \Closure) {
- $value = call_user_func($this->value, $data, $contextParams);
- } else {
- $valuePreparer = new ValuePreparer($this->name, $this->defaultValue);
- $value = $valuePreparer->prepare($data);
+ return call_user_func($this->value, $data, $contextParams);
}
- return $value;
+ $resolver = new ValueResolver();
+ return $resolver->resolve($this->name, $data, $this->defaultValue);
}
/**
@@ -315,7 +315,7 @@ public function renderInput($name, $options, $contextParams = [])
$value = null;
if ($this->type !== self::TYPE_DRAGCOLUMN) {
- $value = $this->prepareValue($contextParams);
+ $value = $this->resolveValue($contextParams);
}
if (isset($options['items'])) {
diff --git a/src/components/ValuePreparer.php b/src/components/ValuePreparer.php
deleted file mode 100644
index 91e01fb..0000000
--- a/src/components/ValuePreparer.php
+++ /dev/null
@@ -1,82 +0,0 @@
-name = $name;
- $this->defaultValue = $defaultValue;
- }
-
- /**
- * @param $data Prepared data
- *
- * @return int|mixed|null|string
- */
- public function prepare($data)
- {
- $value = null;
- if ($data instanceof ActiveRecordInterface) {
- if ($data->canGetProperty($this->name)) {
- $value = $data->{$this->name};
- } else {
- $relation = $data->getRelation($this->name, false);
- if ($relation !== null) {
- $value = $relation->findFor($this->name, $data);
- } else {
- $value = $data->{$this->name};
- }
- }
- } elseif ($data instanceof Model) {
- $value = $data->{$this->name};
- } elseif (is_array($data)) {
- $value = ArrayHelper::getValue($data, $this->name, null);
- } elseif(is_string($data) || is_numeric($data)) {
- $value = $data;
- }
-
- if ($this->defaultValue !== null && $this->isEmpty($value)) {
- $value = $this->defaultValue;
- }
-
- return $value;
- }
-
- protected function isEmpty($value)
- {
- return $value === null || $value === [] || $value === '';
- }
-}
\ No newline at end of file
diff --git a/src/components/ValueResolver.php b/src/components/ValueResolver.php
new file mode 100644
index 0000000..2b78efd
--- /dev/null
+++ b/src/components/ValueResolver.php
@@ -0,0 +1,73 @@
+resolveActiveRecordValue($name, $data);
+ } elseif ($data instanceof Model) {
+ $value = $data->{$name};
+ } elseif (is_array($data)) {
+ $value = $data[$name] ?? null;
+ } elseif(is_string($data) || is_numeric($data)) {
+ $value = $data;
+ }
+
+ if ($defaultValue !== null && $this->isEmpty($value)) {
+ $value = $defaultValue;
+ }
+
+ return $value;
+ }
+
+ /**
+ * @param string $name
+ * @param ActiveRecordInterface $model
+ * @return mixed
+ *
+ * @throws \RuntimeException
+ */
+ private function resolveActiveRecordValue(string $name, ActiveRecordInterface $model)
+ {
+ if ($model->canGetProperty($name)) {
+ return $model->{$name};
+ }
+
+ $relation = $model->getRelation($name, false);
+ if ($relation !== null) {
+ return $relation->findFor($name, $model);
+ }
+
+ throw new \RuntimeException('Failed to resolve value for column: ' . $name);
+ }
+
+ private function isEmpty($value): bool
+ {
+ return $value === null || $value === [] || $value === '';
+ }
+}
diff --git a/tests/unit/components/ValuePreparerTest.php b/tests/unit/components/ValuePreparerTest.php
deleted file mode 100644
index 6f28606..0000000
--- a/tests/unit/components/ValuePreparerTest.php
+++ /dev/null
@@ -1,84 +0,0 @@
-assertEquals($defaultValue, $preparer->prepare(null));
- $this->assertEquals($defaultValue, $preparer->prepare([]));
- $this->assertEquals($defaultValue, $preparer->prepare(''));
- }
-
- public function testPrepareStringOrNumber() {
- $model = new TestModel();
- $preparer = new ValuePreparer();
- $this->assertEquals(1, $preparer->prepare(1));
- $this->assertEquals('1', $preparer->prepare('1'));
- }
-
- public function testPrepareArrayKey() {
- $model = new TestModel();
- $preparer = new ValuePreparer('test');
- $this->assertEquals(1, $preparer->prepare([
- 'test' => 1
- ]));
- }
-
- public function testPrepareModelAttribute() {
- $model = new TestModel();
- $exprectedValue = [
- 'test'
- ];
- $model->email = $exprectedValue;
- $preparer = new ValuePreparer('email');
- $this->assertEquals($exprectedValue, $preparer->prepare($model));
- }
-
- public function testPrepareActiveRecordDirectAttribute() {
- $model = new TestActiveRecord();
- $exprectedValue = 'test';
- $model->email = $exprectedValue;
- $preparer = new ValuePreparer('email');
- $this->assertEquals($exprectedValue, $preparer->prepare($model));
- }
-
- public function testPrepareActiveRecordRelation() {
- $relatedModel = new TestActiveRecordRelated();
- $model = $this->createMock(TestActiveRecord::class);
- $query = $this->createMock(ActiveQuery::class);
- $query->expects($this->once())
- ->method('findFor')
- ->with('testRelation', $model)
- ->willReturn($relatedModel);
-
- $model->expects($this->once())
- ->method('getRelation')
- ->with('testRelation', false)
- ->willReturn($query);
-
- $preparer = new ValuePreparer('testRelation');
-
- $result = $preparer->prepare($model);
-
- $this->assertEquals($relatedModel, $result);
- }
-
- public function testPrepareActiveRecordRelationWithSameAsAttributeName() {
- $model = new TestActiveRecord();
- $relatedModel = new TestActiveRecordRelated();
- $model->testRelation = $relatedModel;
-
- $preparer = new ValuePreparer( 'testRelation');
- $this->assertEquals($relatedModel, $preparer->prepare($model));
- }
-}
\ No newline at end of file
diff --git a/tests/unit/components/ValueResolverTest.php b/tests/unit/components/ValueResolverTest.php
new file mode 100644
index 0000000..0bbd0a8
--- /dev/null
+++ b/tests/unit/components/ValueResolverTest.php
@@ -0,0 +1,90 @@
+assertEquals($defaultValue, $resolver->resolve($columnName, null, $defaultValue));
+ $this->assertEquals($defaultValue, $resolver->resolve($columnName, [], $defaultValue));
+ $this->assertEquals($defaultValue, $resolver->resolve($columnName, '', $defaultValue));
+ }
+
+ public function testResolveWhenDataIsStringOrNumber() {
+ $columnName = 'columnName';
+
+ $resolver = new ValueResolver();
+ $this->assertEquals(100500, $resolver->resolve($columnName, 100500));
+ $this->assertEquals('string', $resolver->resolve($columnName, 'string'));
+ }
+
+ public function testResolveWhenDataIsArray() {
+ $data = [
+ 'test' => 'value'
+ ];
+
+ $resolver = new ValueResolver();
+ $this->assertEquals('value', $resolver->resolve('test', $data));
+ }
+
+ public function testResolveModelProperty() {
+ $expectedValue = 'test@test.com';
+
+ $model = new TestModel();
+ $model->email = $expectedValue;
+
+ $resolver = new ValueResolver();
+ $this->assertEquals($expectedValue, $resolver->resolve('email', $model));
+ }
+
+ public function testResolveActiveRecordDirectAttribute() {
+ $expectedValue = 'test@test.com';
+
+ $model = new TestActiveRecord();
+ $model->email = $expectedValue;
+
+ $resolver = new ValueResolver();
+ $this->assertEquals($expectedValue, $resolver->resolve('email', $model));
+ }
+
+ public function testResolveActiveRecordRelation() {
+ $relatedModel = new TestActiveRecordRelated();
+ $model = $this->createMock(TestActiveRecord::class);
+ $query = $this->createMock(ActiveQuery::class);
+ $query->expects($this->once())
+ ->method('findFor')
+ ->with('testRelation', $model)
+ ->willReturn($relatedModel);
+
+ $model->expects($this->once())
+ ->method('getRelation')
+ ->with('testRelation', false)
+ ->willReturn($query);
+
+ $resolver = new ValueResolver();
+
+ $result = $resolver->resolve('testRelation', $model);
+
+ $this->assertEquals($relatedModel, $result);
+ }
+
+ public function testResolveActiveRecordRelationWithSameNameAsAttributeName() {
+ $relatedModel = new TestActiveRecordRelated();
+
+ $model = new TestActiveRecord();
+ $model->testRelation = $relatedModel;
+
+ $resolver = new ValueResolver();
+ $this->assertEquals($relatedModel, $resolver->resolve('testRelation', $model));
+ }
+}