initial commit
This commit is contained in:
parent
eec097629e
commit
25dbeb389c
10 changed files with 2001 additions and 0 deletions
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
/vendor/
|
11
.gitlab-ci.yml
Normal file
11
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,11 @@
|
|||
image: php:7.1-alpine
|
||||
|
||||
before_script:
|
||||
- apk update
|
||||
- apk add git
|
||||
- curl -sS https://getcomposer.org/installer | php
|
||||
- php composer.phar install
|
||||
|
||||
test:
|
||||
script:
|
||||
- php composer.phar test
|
33
composer.json
Normal file
33
composer.json
Normal file
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"name": "byjoby/html-object-strings",
|
||||
"description": "Abstraction layer for constructing arbitrary HTML tags in PHP",
|
||||
"type": "library",
|
||||
"require": {
|
||||
"byjoby/flatrr": "dev-master"
|
||||
},
|
||||
"license": "MIT",
|
||||
"authors": [{
|
||||
"name": "Joby Elliott",
|
||||
"email": "joby@byjoby.com"
|
||||
}],
|
||||
"minimum-stability": "dev",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"HtmlObjectStrings\\": "src/"
|
||||
}
|
||||
},
|
||||
"autoload-dev": {
|
||||
"psr-4": {
|
||||
"HtmlObjectStrings\\": "tests/"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"test": [
|
||||
"phpunit"
|
||||
]
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^7.4@dev",
|
||||
"stevegrunwell/phpunit-markup-assertions": "dev-master"
|
||||
}
|
||||
}
|
1675
composer.lock
generated
Normal file
1675
composer.lock
generated
Normal file
File diff suppressed because it is too large
Load diff
7
phpunit.xml
Normal file
7
phpunit.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<phpunit>
|
||||
<testsuites>
|
||||
<testsuite name="All Tests">
|
||||
<directory>tests</directory>
|
||||
</testsuite>
|
||||
</testsuites>
|
||||
</phpunit>
|
9
src/A.php
Normal file
9
src/A.php
Normal file
|
@ -0,0 +1,9 @@
|
|||
<?php
|
||||
/* HTML Object Strings | https://gitlab.com/byjoby/html-object-strings | MIT License */
|
||||
namespace HtmlObjectStrings;
|
||||
|
||||
class A extends GenericTag
|
||||
{
|
||||
const TAG = 'a';
|
||||
const SELFCLOSING = false;
|
||||
}
|
136
src/GenericTag.php
Normal file
136
src/GenericTag.php
Normal file
|
@ -0,0 +1,136 @@
|
|||
<?php
|
||||
/* HTML Object Strings | https://gitlab.com/byjoby/html-object-strings | MIT License */
|
||||
namespace HtmlObjectStrings;
|
||||
|
||||
use Flatrr\FlatArray;
|
||||
|
||||
class GenericTag extends FlatArray implements HtmlInterface
|
||||
{
|
||||
const TAG = 'span';
|
||||
const SELFCLOSING = false;
|
||||
|
||||
public function __construct(array $data = null)
|
||||
{
|
||||
parent::__construct($data);
|
||||
$this->merge([
|
||||
'classes' => [],
|
||||
'attributes' => []
|
||||
]);
|
||||
$this->htmlInit();
|
||||
}
|
||||
|
||||
protected function htmlContent()
|
||||
{
|
||||
if (is_array($this['content'])) {
|
||||
$content = implode(PHP_EOL, $this['content']);
|
||||
} else {
|
||||
$content = $this['content'];
|
||||
}
|
||||
return $content;
|
||||
}
|
||||
|
||||
protected function htmlAttributes()
|
||||
{
|
||||
$attr = $this['attributes'];
|
||||
if ($this->classes()) {
|
||||
$attr['class'] = implode(' ', $this->classes());
|
||||
}
|
||||
return $attr;
|
||||
}
|
||||
|
||||
protected function htmlInit()
|
||||
{
|
||||
$this['tag'] = static::TAG;
|
||||
$this['selfclosing'] = static::SELFCLOSING;
|
||||
}
|
||||
|
||||
public function addClass(string $name)
|
||||
{
|
||||
if (!$name) {
|
||||
return;
|
||||
}
|
||||
$classes = $this['classes'];
|
||||
$classes[] = $name;
|
||||
$classes = array_unique($classes);
|
||||
sort($classes);
|
||||
unset($this['classes']);
|
||||
$this['classes'] = $classes;
|
||||
}
|
||||
|
||||
public function hasClass(string $name) : bool
|
||||
{
|
||||
return in_array($name, $this['classes']);
|
||||
}
|
||||
|
||||
public function removeClass(string $name)
|
||||
{
|
||||
$classes = array_filter(
|
||||
$this['classes'],
|
||||
function ($e) use ($name) {
|
||||
return $e != $name;
|
||||
}
|
||||
);
|
||||
sort($classes);
|
||||
unset($this['classes']);
|
||||
$this['classes'] = $classes;
|
||||
}
|
||||
|
||||
public function classes() : array
|
||||
{
|
||||
return $this['classes'];
|
||||
}
|
||||
|
||||
public function attr(string $name, $value = null)
|
||||
{
|
||||
if ($value === false) {
|
||||
unset($this['attributes.'.$name]);
|
||||
return null;
|
||||
}
|
||||
if ($value !== null) {
|
||||
$this['attributes.'.$name] = $value;
|
||||
}
|
||||
if (isset($this['attributes.'.$name])) {
|
||||
return $this['attributes.'.$name];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function data(string $name, $value = null)
|
||||
{
|
||||
return $this->attr("data-$name", $value);
|
||||
}
|
||||
|
||||
public function string() : string
|
||||
{
|
||||
$out = '';
|
||||
//build opening tag
|
||||
$out .= '<'.$this['tag'];
|
||||
//build attributes
|
||||
if ($attr = $this->htmlAttributes()) {
|
||||
foreach ($attr as $key => $value) {
|
||||
if (!"$value") {
|
||||
$out .= " $key";
|
||||
} else {
|
||||
$value = htmlspecialchars($value);
|
||||
$out .= " $key=\"$value\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
//continue t close opening tag and add content and closing tag if needed
|
||||
if ($this['selfclosing']) {
|
||||
$out .= ' />';
|
||||
} else {
|
||||
$out .= '>';
|
||||
//build content
|
||||
$out .= $this->htmlContent();
|
||||
//build closing tag
|
||||
$out .= '</'.$this['tag'].'>';
|
||||
}
|
||||
return $out;
|
||||
}
|
||||
|
||||
public function __toString()
|
||||
{
|
||||
return $this->string();
|
||||
}
|
||||
}
|
20
src/HtmlInterface.php
Normal file
20
src/HtmlInterface.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
/* HTML Object Strings | https://gitlab.com/byjoby/html-object-strings | MIT License */
|
||||
namespace HtmlObjectStrings;
|
||||
|
||||
use Flatrr\FlatArrayInterface;
|
||||
|
||||
interface HtmlInterface extends FlatArrayInterface
|
||||
{
|
||||
public function attr(string $name, $value = null);
|
||||
public function data(string $name, $value = null);
|
||||
|
||||
public function addClass(string $name);
|
||||
public function hasClass(string $name) : bool;
|
||||
public function removeClass(string $name);
|
||||
public function classes() : array;
|
||||
|
||||
public function string() : string;
|
||||
|
||||
public function __toString();
|
||||
}
|
30
src/Input.php
Normal file
30
src/Input.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
/* HTML Object Strings | https://gitlab.com/byjoby/html-object-strings | MIT License */
|
||||
namespace HtmlObjectStrings;
|
||||
|
||||
class Input extends GenericTag
|
||||
{
|
||||
const TAG = 'input';
|
||||
const SELFCLOSING = true;
|
||||
const TYPE = 'text';
|
||||
|
||||
protected function htmlInit()
|
||||
{
|
||||
parent::htmlInit();
|
||||
$this->attr('type', static::TYPE);
|
||||
}
|
||||
|
||||
protected function htmlContent()
|
||||
{
|
||||
return parent::htmlContent();
|
||||
}
|
||||
|
||||
protected function htmlAttributes()
|
||||
{
|
||||
$attr = parent::htmlAttributes();
|
||||
if ($value = $this->htmlContent()) {
|
||||
$attr['value'] = $value;
|
||||
}
|
||||
return $attr;
|
||||
}
|
||||
}
|
79
tests/GenericTagTest.php
Normal file
79
tests/GenericTagTest.php
Normal file
|
@ -0,0 +1,79 @@
|
|||
<?php
|
||||
/* HTML Object Strings | https://gitlab.com/byjoby/html-object-strings | MIT License */
|
||||
declare(strict_types=1);
|
||||
namespace HtmlObjectStrings;
|
||||
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class GenericTagTest extends TestCase
|
||||
{
|
||||
use \SteveGrunwell\PHPUnit_Markup_Assertions\MarkupAssertionsTrait;
|
||||
|
||||
public function testBasicClassManagement()
|
||||
{
|
||||
/*
|
||||
This section tests the basic class adding, removing, and output features
|
||||
*/
|
||||
$h = new GenericTag();
|
||||
//default is no classes
|
||||
$this->assertEquals([], $h->classes());
|
||||
$this->assertFalse($h->hasClass('foo'));
|
||||
//adding a class
|
||||
$h->addClass('foo');
|
||||
//should now exist
|
||||
$this->assertEquals(['foo'], $h->classes());
|
||||
$this->assertTrue($h->hasClass('foo'));
|
||||
//adding a second time shouldn't change anything
|
||||
$h->addClass('foo');
|
||||
$this->assertEquals(['foo'], $h->classes());
|
||||
$this->assertTrue($h->hasClass('foo'));
|
||||
//adding another class
|
||||
$h->addClass('bar');
|
||||
//should now exist, and classes should be in alphabetical order
|
||||
$this->assertEquals(['bar','foo'], $h->classes());
|
||||
$this->assertTrue($h->hasClass('bar'));
|
||||
//removing a class
|
||||
$h->addClass('abc');
|
||||
$h->removeClass('bar');
|
||||
//bar should now not exist, and classes should be in alphabetical order
|
||||
$this->assertEquals(['abc','foo'], $h->classes());
|
||||
$this->assertFalse($h->hasClass('bar'));
|
||||
}
|
||||
|
||||
public function testDataAndAttributeManagement()
|
||||
{
|
||||
/*
|
||||
This section tests the basic getting/setting of attributes
|
||||
*/
|
||||
$h = new GenericTag();
|
||||
//set and get an attribute
|
||||
$h->attr('foo', 'bar');
|
||||
$this->assertEquals('bar', $h->attr('foo'));
|
||||
//set and get data
|
||||
$h->data('foo', 'baz');
|
||||
$this->assertEquals('baz', $h->data('foo'));
|
||||
$this->assertEquals('baz', $h->attr('data-foo'));
|
||||
$this->assertEquals('bar', $h->attr('foo'));
|
||||
}
|
||||
|
||||
public function testMarkupOutput()
|
||||
{
|
||||
/*
|
||||
Test that output has the correct attributes and classes for what was
|
||||
configured into the object
|
||||
*/
|
||||
$h = new GenericTag();
|
||||
$h['tag'] = 'div';
|
||||
$h['selfclosing'] = false;
|
||||
$h['content'] = 'markup content';
|
||||
$h->attr('id', 'h');
|
||||
$h->data('foo', 'bar');
|
||||
$h->addClass('class-foo');
|
||||
$h->addClass('class-bar');
|
||||
//should be a div tag
|
||||
$this->assertContainsSelector('div', "$h");
|
||||
$this->assertContainsSelector('div#h', "$h");
|
||||
$this->assertContainsSelector('div[data-foo="bar"]', "$h");
|
||||
$this->assertContainsSelector('div.class-foo.class-bar', "$h");
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue