Skip to content

Commit

Permalink
Lazy data load for ngrest plugin (#647)
Browse files Browse the repository at this point in the history
* Block Preview styling

* Tooltip preview fix #246

* Date plugin with custom format

* Changelog for #270

* Refactored namespace using

* Connection lost handling

* Unit test fixed close #229

* CONNECTION_ID only available in mysql

* Block Preview styling

* Tooltip preview fix #246

* travis tests with php 7.4

* clean up dist

* attache find behaviours

* Changelogs

* Unit tests

* phpdocs & changelog

* Update NgRestModel.php

* Update NgRestModel.php

* Update NgRestModel.php

* Update TestNgRestModel.php

* lazy data load for ngrest plugin

* changelog

* phpdocs for LazyDataLoadTrait

* lazyDataLoad Test

* lazyDataLoad Test

* lazyDataLoad Test

Co-authored-by: Basil <git@nadar.io>
  • Loading branch information
boehsermoe and nadar authored Jun 14, 2021
1 parent 457cfa2 commit b05bb40
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 8 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ In order to read more about upgrading and BC breaks have a look at the [UPGRADE

> This release contains new migrations and requires to run the migrate command after updating. Check the [UPGRADE document](UPGRADE.md) to read more about breaking changes.
+ [#647](https://github.com/luyadev/luya-module-admin/pull/647) Lazy data load for ngrest plugin.
+ [#635](https://github.com/luyadev/luya-module-admin/pull/635) New migration database file, as new attributes are available for properties, images and files
+ [#298](https://github.com/luyadev/luya-module-admin/issues/298) Added new NgRest Plugin `SelectAsyncApi` which can be used to change the select based on certain context variables in real time, its also known as "dependent select".
+ [#642](https://github.com/luyadev/luya-module-admin/pull/642) Example usage for admin/proxy machine in detail window.
Expand Down
23 changes: 21 additions & 2 deletions src/ngrest/plugins/CheckboxList.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use luya\admin\helpers\I18n;
use luya\admin\ngrest\base\Plugin;
use luya\admin\traits\LazyDataLoadTrait;
use luya\helpers\ArrayHelper;
use luya\helpers\StringHelper;

Expand All @@ -21,13 +22,31 @@
* }
* ```
*
* Or use a closure for lazy data load:
*
* ```php
* public function ngRestAttributeTypes()
* {
* return [
* 'genres' => ['checkboxList', 'data' => function () {
* return new Query()->all();
* }],
* ];
* }
* ```
*
* The plugin stores the value of the selected checkbox items as json into the database.
*
* @author Basil Suter <basil@nadar.io>
* @since 1.0.0
*/
class CheckboxList extends Plugin
{
use LazyDataLoadTrait;

/**
* @var array|\Closure
*/
public $data = [];

public $i18nEmptyValue = [];
Expand Down Expand Up @@ -60,10 +79,10 @@ protected function getItems()
{
$data = [];

foreach ($this->data as $value => $label) {
foreach ($this->lazyLoadData($this->data) as $value => $label) {
$data[] = ['value' => $value, 'label' => $label];
}

return ['items' => ArrayHelper::typeCast($data)];
}

Expand Down
17 changes: 16 additions & 1 deletion src/ngrest/plugins/SelectArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

namespace luya\admin\ngrest\plugins;

use luya\admin\traits\LazyDataLoadTrait;
use luya\helpers\ArrayHelper;

/**
Expand All @@ -15,6 +16,18 @@
* 'genres' => ['selectArray', 'data' => [1 => 'Male', 2 => 'Female']],
* }
* ```
* Or use a closure for lazy data load:
*
* ```php
* public function ngRestAttributeTypes()
* {
* return [
* 'genres' => ['selectArray', 'data' => function () {
* return new Query()->all();
* }],
* ];
* }
* ```
*
* @property array $data Setter/Getter for the dropdown values.
*
Expand All @@ -23,6 +36,8 @@
*/
class SelectArray extends Select
{
use LazyDataLoadTrait;

private $_data;

/**
Expand All @@ -44,7 +59,7 @@ public function getData()
{
$cleandata = [];

foreach ($this->_data as $key => $value) {
foreach ($this->loadData($this->_data) as $key => $value) {
$cleandata[] = [
'value' => $key,
'label' => $value,
Expand Down
22 changes: 17 additions & 5 deletions src/ngrest/plugins/SortRelationArray.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,37 @@

namespace luya\admin\ngrest\plugins;

/**
use luya\admin\traits\LazyDataLoadTrait;/**
* Sort Relation Array Plugin.
*
* Generate a multi selectable and sortable list based on an arry input.
*
* Example usage:
*
* ```php
* public function ngRestAttributeTypes()
* {
* 'genres' => ['sortRelationArray', 'data' => [1 => 'Jazz', 2 => 'Funk', 3 => 'Soul']
* }
* ```
*
* Or use a closure for lazy data load:
*
* ```php
* public function ngRestAttributeTypes()
* {
* return [
* 'genres' => ['sortRelationArray', 'data' => function () {
* return new Query()->all();
* }],
* ];
* }
* ```
*
* @author Basil Suter <basil@nadar.io>
* @since 1.0.0
*/
class SortRelationArray extends SortRelation
{
use LazyDataLoadTrait;

private $_data;

/**
Expand All @@ -29,7 +41,7 @@ class SortRelationArray extends SortRelation
public function getData()
{
$data = [];
foreach ($this->_data as $value => $label) {
foreach ($this->loadData($this->_data) as $value => $label) {
$data[] = ['value' => $value, 'label' => $label];
}

Expand Down
49 changes: 49 additions & 0 deletions src/traits/LazyDataLoadTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

namespace luya\admin\traits;

/**
* Trait to enable lazy load for NgRest plugins.
*
* For a example for CheckboxList:
*
* ```php
* public function ngRestAttributeTypes()
* {
* return [
* 'genres' => ['checkboxList', 'data' => function () {
* return new Query()->all();
* }],
* ];
* }
* ```
*
* @author Bennet Klarhölter <boehsermoe@me.com>
* @since 4.0.0
*/
trait LazyDataLoadTrait
{
/**
* If the given data is a closure it will call it and return the result of the function.
* Function will only execute if the data are really need to load.
*
* If the given data is no closure it will return the directly data.
*
* ```
* $this->lazyLoadData(function () {
* return Query::find()->all();
* });
* ```
*
* @param mixed|\Closure $data
* @return mixed|\Traversable
*/
protected function lazyLoadData($data)
{
if (is_callable($data)) {
return call_user_func($data);
}

return $data;
}
}
30 changes: 30 additions & 0 deletions tests/admin/ngrest/plugins/CheckboxListTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,34 @@ public function testSaveEventArrayFrontendInput()

$this->assertSame('[{"value":1},{"value":2}]', $user->id);
}

public function testLazyLoad()
{
$dataLoaded = false;

$plugin = new CheckboxList([
'alias' => 'alias',
'name' => 'id',
'i18n' => false,
'data' => function () use (&$dataLoaded) {
$dataLoaded = true;
return ['some' => 'data'];
},
]);

$this->assertFalse($dataLoaded, 'Data should load lazy.');

$model = new UserFixture();
$model->load();
$user = $model->getModel('user1');
$user->id = '[{"value":1},{"value":2}]';

$event = new Event();
$event->sender = $user;

$plugin->onAfterListFind($event);

$this->assertTrue($dataLoaded, 'Lazy laod was not called.');

}
}
56 changes: 56 additions & 0 deletions tests/admin/traits/LazyDataLoadTraitTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
<?php

namespace admintests\admin\traits;

use admintests\AdminModelTestCase;
use admintests\data\fixtures\UserFixture;
use luya\admin\traits\LazyDataLoadTrait;

class LazyDataLoadTraitTest extends AdminModelTestCase
{
public function testWithAnonymousFunction()
{
$dataLoaded = false;

$mock = new LazyDataLoadTraitMock();
$mock->data = function () use (&$dataLoaded) {
$dataLoaded = true;
return 'FOO';
};

$this->assertEquals('FOO', $mock->getData());
$this->assertTrue($dataLoaded);
}

public function testWithCallableArray()
{
$this->lazyDataLoadFunctionCalled = false;

$mock = new LazyDataLoadTraitMock();
$mock->data = [$this, 'lazyDataLoadFunction'];

$this->assertEquals(self::class . '::lazyDataLoadFunction', $mock->getData());
$this->assertTrue($this->lazyDataLoadFunctionCalled);
}

protected $lazyDataLoadFunctionCalled = false;

public function lazyDataLoadFunction()
{
$this->lazyDataLoadFunctionCalled = true;

return __METHOD__;
}
}

class LazyDataLoadTraitMock
{
use LazyDataLoadTrait;

public $data;

public function getData()
{
return $this->lazyLoadData($this->data);
}
}

0 comments on commit b05bb40

Please sign in to comment.