Skip to content

Commit d9172a3

Browse files
author
neustadt
committed
first commit
0 parents  commit d9172a3

File tree

6 files changed

+347
-0
lines changed

6 files changed

+347
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.idea
2+
.DS_Store
3+
composer.lock
4+
vendor

HtmlTagReplace/HtmlTagReplace.php

+167
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
<?php
2+
3+
namespace HtmlTagReplace;
4+
5+
/**
6+
* Class HtmlTagReplace
7+
* @package HtmlTagReplace
8+
*/
9+
class HtmlTagReplace
10+
{
11+
/**
12+
* @var string
13+
*/
14+
private $markup = '';
15+
16+
/**
17+
* HtmlTagReplace constructor.
18+
* @param $markup
19+
*/
20+
public function __construct($markup)
21+
{
22+
$this->markup = $markup;
23+
}
24+
25+
/**
26+
* @return string
27+
*/
28+
public function getMarkup()
29+
{
30+
return $this->markup;
31+
}
32+
33+
/**
34+
* @param string $markup
35+
*/
36+
public function setMarkup($markup)
37+
{
38+
$this->markup = $markup;
39+
}
40+
41+
/**
42+
* @param $search
43+
* @param $replace
44+
* @param bool $closingTag
45+
* @param array $argumentsReplace
46+
* @param string $arguments
47+
* @param string $append
48+
* @param string $prepend
49+
* @return $this
50+
*/
51+
public function replaceTag(
52+
$search,
53+
$replace,
54+
$closingTag = false,
55+
$argumentsReplace = [],
56+
$arguments = '',
57+
$append = '',
58+
$prepend = ''
59+
)
60+
{
61+
$pattern = '/<' . $search . '(.*?)>';
62+
$replacement = '<' . $replace . ' ' . $arguments . '$1>';
63+
64+
if ($closingTag) {
65+
$pattern .= '(.*?)<\/' . $search . '>';
66+
$replacement .= '$2</' . $replace . '>';
67+
}
68+
69+
$pattern .= '/is';
70+
$replacement = $prepend . $replacement . $append;
71+
72+
if (empty($argumentsReplace)) {
73+
$this->setMarkup(
74+
preg_replace(
75+
$pattern,
76+
$replacement,
77+
$this->getMarkup()
78+
)
79+
);
80+
} else {
81+
$this->setMarkup(
82+
preg_replace_callback(
83+
$pattern,
84+
function ($matches) use ($replacement, $argumentsReplace) {
85+
return $this->replaceArguments(
86+
$matches,
87+
$replacement,
88+
$argumentsReplace
89+
);
90+
},
91+
$this->getMarkup()
92+
)
93+
);
94+
}
95+
96+
return $this;
97+
}
98+
99+
/**
100+
* @param array $matches
101+
* @param string $replacement
102+
* @param array $argumentsReplace
103+
* @return string
104+
*/
105+
private function replaceArguments(
106+
$matches,
107+
$replacement,
108+
$argumentsReplace
109+
)
110+
{
111+
$replacement = str_replace(
112+
['$1', '$2'],
113+
'%s',
114+
$replacement
115+
);
116+
117+
if (isset($matches[0])) {
118+
unset($matches[0]);
119+
}
120+
121+
if (isset($matches[1])) {
122+
$arguments = preg_split('/ (?=\w+=)/', $matches[1]);
123+
124+
foreach ($arguments as $key => $argument) {
125+
$pair = explode('=', $argument);
126+
if (isset($argumentsReplace[trim($pair[0])])) {
127+
$newTag = $argumentsReplace[trim($pair[0])];
128+
if (!is_array($newTag)) {
129+
if ($newTag === false) {
130+
unset($arguments[$key]);
131+
continue;
132+
}
133+
$pair[0] = $newTag;
134+
$arguments[$key] = join('=', $pair);
135+
} else {
136+
$clones = [];
137+
foreach ($newTag as $clone) {
138+
$pair[0] = $clone;
139+
$clones[] = join('=', $pair);
140+
}
141+
$arguments[$key] = join(' ', $clones);
142+
}
143+
}
144+
}
145+
146+
$matches[1] = join(' ', $arguments);
147+
}
148+
149+
return vsprintf($replacement, $matches);
150+
}
151+
152+
/**
153+
* @return $this
154+
*/
155+
public function compress()
156+
{
157+
$this->setMarkup(
158+
preg_replace(
159+
['/\n/','/\>[^\S ]+/s','/[^\S ]+\</s','/(\s)+/s'],
160+
[' ','>','<','\\1'],
161+
$this->getMarkup()
162+
)
163+
);
164+
165+
return $this;
166+
}
167+
}

HtmlTagReplace/Test/ReplaceTest.php

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
namespace HtmlTagReplace\Test;
4+
5+
use HtmlTagReplace\HtmlTagReplace;
6+
7+
/**
8+
* Class ReplaceTest
9+
* @package HtmlTagReplace\Test
10+
*/
11+
class ReplaceTest extends \PHPUnit_Framework_TestCase
12+
{
13+
/**
14+
* @var HtmlTagReplace
15+
*/
16+
private $replacer;
17+
18+
public function __construct($name = NULL, array $data = array(), $dataName = '')
19+
{
20+
parent::__construct($name, $data, $dataName);
21+
22+
$this->replacer = new HtmlTagReplace(<<<EOF
23+
<img src="#" alt="nope">
24+
<img src="#">
25+
<div id="foo">bar</div>
26+
<em class="foo">bar</em>
27+
<input type="text" name="foo">
28+
EOF
29+
);
30+
}
31+
32+
public function testMarkupManipulation()
33+
{
34+
$expected = <<<EOF
35+
<a title="show image" href="#">show image</a> <a title="show image" href="#">show image</a> <hr><article class="foo">bar</article> <strong class="foo">bar</strong> <input type="text" name="foo" id="foo">
36+
EOF;
37+
38+
39+
$actual = $this->replacer->replaceTag(
40+
'img',
41+
'a',
42+
false,
43+
['src' => 'href', 'alt' => false],
44+
'title="show image"',
45+
'show image</a>'
46+
)->replaceTag(
47+
'div',
48+
'article',
49+
true,
50+
['id' => 'class'],
51+
null,
52+
null,
53+
'<hr>'
54+
)->replaceTag(
55+
'em',
56+
'strong',
57+
true
58+
)->replaceTag(
59+
'input',
60+
'input',
61+
false,
62+
['name' => ['name', 'id']]
63+
)->compress()->getMarkup();
64+
65+
66+
$this->assertEquals($expected, $actual);
67+
}
68+
}

README.md

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
# HtmlTagReplace
2+
3+
a helper to replace and enhance html tags and their attributes.
4+
5+
## Features
6+
7+
* Append, prepend and switch tags.
8+
* Add custom attributes to tags
9+
* Switch, clone or remove attributes.
10+
11+
## Usage
12+
13+
Create an Instance of `HtmlTagReplace` passing existing markup.
14+
15+
Use `replaceTag` method of said instance passing the following arguments:
16+
17+
* `search` Name of the tag to be replaced
18+
* `replace` Name of the new tag
19+
* `closingTag` (bool, default: false) defines whether searched tag has closing tag
20+
* `argumentsReplace` (array) key-value pairs (`search => replace`) of attributes to be replaced. Multidimensional (`search => array`) to clone value into multiple arguments.
21+
* `arguments` custom arguments injected
22+
* `append` injected after targeted tag
23+
* `prepend` injected before targeted tag
24+
25+
You can call the method `compress` to minify the markup.
26+
27+
Finally retrieve the altered markup calling `getMarkup`
28+
29+
## Example
30+
31+
```php
32+
$markup = '
33+
<img src="#" alt="foo">
34+
<img src="#">
35+
<div id="foo">bar</div>
36+
<em class="foo">bar</em>
37+
<input type="text" name="foo">
38+
';
39+
40+
$replacer = new HtmlTagReplace($markup);
41+
42+
echo $replacer->replaceTag(
43+
'img',
44+
'a',
45+
false,
46+
['src' => 'href', 'alt' => false],
47+
'title="show image"',
48+
'show image</a>'
49+
)->replaceTag(
50+
'div',
51+
'article',
52+
true,
53+
['id' => 'class'],
54+
null,
55+
null,
56+
'<hr>'
57+
)->replaceTag(
58+
'em',
59+
'strong',
60+
true
61+
)->replaceTag(
62+
'input',
63+
'input',
64+
false,
65+
['name' => ['name', 'id']]
66+
)->compress()->getMarkup();
67+
```
68+
69+
will result in (not minified for readability):
70+
71+
```html
72+
<a title="show image" href="#">show image</a>
73+
<a title="show image" href="#">show image</a>
74+
<hr><article class="foo">bar</article>
75+
<strong class="foo">bar</strong>
76+
<input type="text" name="foo" id="foo">
77+
```
78+
79+
# Todos
80+
81+
* add more filter options for targeting tags
82+
* optimize method for filtering and replacing arguments
83+
* content manipulation
84+
* synchronized replacement

composer.json

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
{
2+
"name": "dneustadt/html-tag-replace",
3+
"version": "1.0.0",
4+
"keywords": ["dom", "replace", "tags", "attributes", "markup"],
5+
"description": "Replace and enhance markup tags and/or attributes",
6+
"homepage": "https://davidneustadt.de",
7+
"license": "MIT",
8+
"require-dev": {
9+
"phpunit/phpunit": "3.7.*"
10+
},
11+
"autoload": {
12+
"psr-4": {
13+
"HtmlTagReplace\\": "HtmlTagReplace"
14+
}
15+
}
16+
}

phpunit.xml

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<phpunit colors="true">
3+
<testsuites>
4+
<testsuite name="HtmlTagReplace Tests">
5+
<directory>./HtmlTagReplace/Test/</directory>
6+
</testsuite>
7+
</testsuites>
8+
</phpunit>

0 commit comments

Comments
 (0)