Skip to content

Commit 2d7d511

Browse files
committed
Project Setup
1 parent d080536 commit 2d7d511

11 files changed

+251
-5
lines changed

.gitignore

+1-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
11
composer.phar
2+
composer.lock
23
/vendor/
3-
4-
# Commit your application's lock file https://getcomposer.org/doc/01-basic-usage.md#commit-your-composer-lock-file-to-version-control
5-
# You may choose to ignore a library lock file http://getcomposer.org/doc/02-libraries.md#lock-file
6-
# composer.lock

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -1 +1,3 @@
1-
# mv
1+
# mv - Model View
2+
3+
Recommended structure for frontend Model/View

composer.json

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"require": {
3+
"packaged/safehtml": "^2.2",
4+
"packaged/ui": "^1.7",
5+
"packaged/context": "^1.0",
6+
"packaged/helpers": "^1.0|^2.0"
7+
},
8+
"require-dev": {
9+
"cubex/framework": "^4.17",
10+
"phpunit/phpunit": "^9"
11+
},
12+
"autoload": {
13+
"psr-4": {
14+
"Cubex\\Mv\\": "src"
15+
}
16+
},
17+
"autoload-dev": {
18+
"psr-4": {
19+
"Cubex\\Mv\\Tests\\": "tests"
20+
}
21+
}
22+
}

src/AbstractView.php

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
namespace Cubex\Mv;
3+
4+
abstract class AbstractView implements View
5+
{
6+
protected ?Model $_model;
7+
8+
public function __construct(?Model $data) { $this->_model = $data; }
9+
10+
public function render(): string
11+
{
12+
return $this->produceSafeHTML()->getContent();
13+
}
14+
}

src/ArrayModel.php

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
namespace Cubex\Mv;
3+
4+
class ArrayModel extends ViewModel
5+
{
6+
protected array $_data = [];
7+
8+
public function clear()
9+
{
10+
$this->_data = [];
11+
return $this;
12+
}
13+
14+
public function set(array $data = [])
15+
{
16+
$this->_data = $data;
17+
return $this;
18+
}
19+
20+
public function addItem($value, string $key = null)
21+
{
22+
if($key === null)
23+
{
24+
$this->_data[] = $value;
25+
}
26+
else
27+
{
28+
$this->_data[$key] = $value;
29+
}
30+
return $this;
31+
}
32+
33+
public function getData()
34+
{
35+
return $this->_data;
36+
}
37+
38+
public function jsonSerialize()
39+
{
40+
return $this->_data;
41+
}
42+
43+
}

src/JsonView.php

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
namespace Cubex\Mv;
3+
4+
use Packaged\SafeHtml\SafeHtml;
5+
6+
class JsonView extends AbstractView
7+
{
8+
protected int $_flags = JSON_PRETTY_PRINT;
9+
10+
public function produceSafeHTML(): SafeHtml
11+
{
12+
return new SafeHtml($this->render());
13+
}
14+
15+
/**
16+
* @param int $flags
17+
*
18+
* Bitmask consisting of <b>JSON_HEX_QUOT</b>,
19+
* <b>JSON_HEX_TAG</b>,
20+
* <b>JSON_HEX_AMP</b>,
21+
* <b>JSON_HEX_APOS</b>,
22+
* <b>JSON_NUMERIC_CHECK</b>,
23+
* <b>JSON_PRETTY_PRINT</b>,
24+
* <b>JSON_UNESCAPED_SLASHES</b>,
25+
* <b>JSON_FORCE_OBJECT</b>,
26+
* <b>JSON_UNESCAPED_UNICODE</b>.
27+
* <b>JSON_THROW_ON_ERROR</b> The behaviour of these
28+
* constants is described on
29+
* the JSON constants page.
30+
*
31+
* @return $this
32+
*/
33+
public function setFlags(int $flags = 0)
34+
{
35+
$this->_flags = $flags;
36+
return $this;
37+
}
38+
39+
public function render(): string
40+
{
41+
return json_encode($this->_model, $this->_flags);
42+
}
43+
}

src/Model.php

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
namespace Cubex\Mv;
3+
4+
interface Model extends \JsonSerializable
5+
{
6+
}

src/View.php

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
namespace Cubex\Mv;
3+
4+
use Packaged\SafeHtml\ISafeHtmlProducer;
5+
use Packaged\Ui\Renderable;
6+
7+
/**
8+
* A view must be constructed with a model
9+
*/
10+
interface View extends ISafeHtmlProducer, Renderable
11+
{
12+
public function __construct(?Model $data);
13+
}

src/ViewModel.php

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?php
2+
namespace Cubex\Mv;
3+
4+
use Packaged\Context\ContextAware;
5+
use Packaged\Context\ContextAwareTrait;
6+
use Packaged\Helpers\Objects;
7+
8+
class ViewModel implements Model, ContextAware
9+
{
10+
use ContextAwareTrait;
11+
12+
public function jsonSerialize()
13+
{
14+
$values = Objects::propertyValues($this);
15+
return empty($values) ? $this : $values;
16+
}
17+
18+
public function createView(string $viewClass)
19+
{
20+
if(!class_exists($viewClass))
21+
{
22+
throw new \Exception("Invalid view class provided '$viewClass'");
23+
}
24+
$view = new $viewClass($this);
25+
if($view instanceof ContextAware && $this->hasContext())
26+
{
27+
$view->setContext($this->getContext());
28+
}
29+
return $view;
30+
}
31+
}

tests/JsonViewTest.php

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
namespace Cubex\Mv\Tests;
3+
4+
use Cubex\Mv\ArrayModel;
5+
use Cubex\Mv\JsonView;
6+
use Cubex\Mv\Model;
7+
use Cubex\Mv\ViewModel;
8+
use PHPUnit\Framework\TestCase;
9+
10+
class JsonViewTest extends TestCase
11+
{
12+
/**
13+
* @dataProvider viewResults
14+
*/
15+
public function testResults($testName, $model, $flags, $expect)
16+
{
17+
$view = new JsonView($model);
18+
if(is_int($flags))
19+
{
20+
$view->setFlags($flags);
21+
}
22+
self::assertEquals($expect, $view->render(), $testName . " - Render");
23+
self::assertEquals($expect, $view->produceSafeHTML()->getContent(), $testName . " - SafeHtml");
24+
}
25+
26+
public function viewResults()
27+
{
28+
return [
29+
["Null Check", null, null, "null"],
30+
["Simple Json", new JsonViewTestData(), 0, '{"a":"b"}'],
31+
["Empty", new ViewModel(), 0, '{}'],
32+
["Array", $this->_arrayModel(), 0, '["a","b","c"]'],
33+
];
34+
}
35+
36+
protected function _arrayModel()
37+
{
38+
$model = new ArrayModel();
39+
$model->addItem("a");
40+
$model->addItem("b");
41+
$model->addItem("c");
42+
return $model;
43+
}
44+
}
45+
46+
class JsonViewTestData implements Model
47+
{
48+
public function jsonSerialize()
49+
{
50+
return ["a" => "b"];
51+
}
52+
}

tests/ViewModelTest.php

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<?php
2+
namespace Cubex\Mv\Tests;
3+
4+
use Cubex\Mv\JsonView;
5+
use Cubex\Mv\ViewModel;
6+
use PHPUnit\Framework\TestCase;
7+
8+
class ViewModelTest extends TestCase
9+
{
10+
public function testViewCreation()
11+
{
12+
$model = new ViewModel();
13+
$view = $model->createView(JsonView::class);
14+
self::assertInstanceOf(JsonView::class, $view);
15+
}
16+
17+
public function testInvalidClassViewCreation()
18+
{
19+
self::expectExceptionMessage("Invalid view class provided 'NotAValidClass'");
20+
$model = new ViewModel();
21+
$model->createView("NotAValidClass");
22+
}
23+
}

0 commit comments

Comments
 (0)