├── .gitignore
├── .scrutinizer.yml
├── .travis.yml
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── composer.json
├── examples
├── 001.css
├── cssZenGarden.html
└── simple.php
├── library
└── Respect
│ └── Template
│ ├── Adapter.php
│ ├── Adapters
│ ├── A.php
│ ├── AbstractAdapter.php
│ ├── Dom.php
│ ├── HtmlElement.php
│ ├── String.php
│ └── Traversable.php
│ ├── Decorators
│ ├── AbstractDecorator.php
│ ├── Append.php
│ ├── Clean.php
│ ├── CleanAppend.php
│ └── Replace.php
│ ├── Document.php
│ ├── Html.php
│ ├── HtmlElement.php
│ └── Query.php
├── phpunit.xml.dist
└── tests
└── library
└── Respect
└── Template
├── AdapterTest.php
├── Adapters
├── ATest.php
├── HtmlElementTest.php
├── StringTest.php
└── TraversableTest.php
├── Decorators
├── AppendTest.php
├── CleanAppendTest.php
├── CleanTest.php
└── ReplaceTest.php
├── HtmlElementTest.php
└── HtmlTest.php
/.gitignore:
--------------------------------------------------------------------------------
1 | Makefile
2 | phpunit.xml
3 | vendor/
4 | *.lock
5 |
--------------------------------------------------------------------------------
/.scrutinizer.yml:
--------------------------------------------------------------------------------
1 | filter:
2 | excluded_paths:
3 | - tests/*
4 |
5 | checks:
6 | php:
7 | code_rating: true
8 |
9 | tools:
10 | external_code_coverage: true
11 | php_analyzer: true
12 | php_changetracking: true
13 | php_code_sniffer:
14 | config:
15 | standard: "PSR2"
16 | php_cpd: true
17 | php_mess_detector: true
18 | php_pdepend: true
19 | sensiolabs_security_checker: true
20 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | sudo:
2 | false
3 |
4 | language:
5 | php
6 |
7 | php:
8 | - 5.3
9 | - 5.4
10 | - 5.5
11 | - 5.6
12 | - hhvm
13 | - hhvm-nightly
14 |
15 | cache:
16 | directories:
17 | - vendor
18 |
19 | before_script:
20 | - composer install --dev --no-interaction --prefer-source
21 |
22 | script:
23 | - vendor/bin/phpunit --configuration phpunit.xml.dist --colors --coverage-clover=coverage.clover
24 |
25 | after_script:
26 | - wget https://scrutinizer-ci.com/ocular.phar
27 | - php ocular.phar code-coverage:upload --format=php-clover coverage.clover
28 |
29 | matrix:
30 | allow_failures:
31 | - php: hhvm
32 | - php: hhvm-nightly
33 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to Respect\Template
2 |
3 | Contributions to Respect\Template are always welcome. You make our lives easier by
4 | sending us your contributions through [GitHub pull requests](http://help.github.com/pull-requests).
5 |
6 | Pull requests for bug fixes must be based on the current stable branch whereas
7 | pull requests for new features must be based on `master`.
8 |
9 | Due to time constraints, we are not always able to respond as quickly as we
10 | would like. Please do not take delays personal and feel free to remind us here,
11 | on IRC, or on Gitter if you feel that we forgot to respond.
12 |
13 | ## Using Respect\Template From a Git Checkout
14 |
15 | The following commands can be used to perform the initial checkout of Respect\Template:
16 |
17 | ```shell
18 | git clone git://github.com/Respect/Template.git
19 | cd Template
20 | ```
21 |
22 | Retrieve Respect\Template's dependencies using [Composer](http://getcomposer.org/):
23 |
24 | ```shell
25 | composer install
26 | ```
27 |
28 | ## Running Tests
29 |
30 | After run `composer install` on the library's root directory you must run PHPUnit.
31 |
32 | ### Linux
33 |
34 | You can test the project using the commands:
35 | ```shell
36 | $ vendor/bin/phpunit
37 | ```
38 |
39 | ### Windows
40 |
41 | You can test the project using the commands:
42 | ```shell
43 | > vendor\bin\phpunit
44 | ```
45 |
46 | No test should fail.
47 |
48 | You can tweak the PHPUnit's settings by copying `phpunit.xml.dist` to `phpunit.xml`
49 | and changing it according to your needs.
50 |
51 | ## Standards
52 |
53 | We are trying to follow the [PHP-FIG](http://www.php-fig.org)'s standards, so
54 | when you send us a pull request, be sure you are following them.
55 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2009-2015, Alexandre Gomes Gaigalas.
2 | All rights reserved.
3 |
4 | Redistribution and use in source and binary forms, with or without modification,
5 | are permitted provided that the following conditions are met:
6 |
7 | * Redistributions of source code must retain the above copyright notice,
8 | this list of conditions and the following disclaimer.
9 |
10 | * Redistributions in binary form must reproduce the above copyright notice,
11 | this list of conditions and the following disclaimer in the documentation
12 | and/or other materials provided with the distribution.
13 |
14 | * Neither the name of Alexandre Gomes Gaigalas nor the names of its
15 | contributors may be used to endorse or promote products derived from this
16 | software without specific prior written permission.
17 |
18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
25 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 |
29 | Copyright (c) 2005-2011, Zend Technologies USA, Inc.
30 | All rights reserved.
31 |
32 | Redistribution and use in source and binary forms, with or without modification,
33 | are permitted provided that the following conditions are met:
34 |
35 | * Redistributions of source code must retain the above copyright notice,
36 | this list of conditions and the following disclaimer.
37 |
38 | * Redistributions in binary form must reproduce the above copyright notice,
39 | this list of conditions and the following disclaimer in the documentation
40 | and/or other materials provided with the distribution.
41 |
42 | * Neither the name of Zend Technologies USA, Inc. nor the names of its
43 | contributors may be used to endorse or promote products derived from this
44 | software without specific prior written permission.
45 |
46 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
47 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
48 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
49 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
50 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
51 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
52 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
53 | ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
54 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
55 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
56 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Respect\Template
2 | [](http://travis-ci.org/Respect/Template)
3 | [](https://scrutinizer-ci.com/g/Respect/Template/?branch=master)
4 | [](https://packagist.org/packages/respect/template)
5 | [](https://packagist.org/packages/respect/template)
6 | [](https://packagist.org/packages/respect/template)
7 |
8 | Pure HTML Templates.
9 |
10 | ## Installation
11 |
12 | The package is available on [Packagist](https://packagist.org/packages/respect/template).
13 | You can install it using [Composer](http://getcomposer.org).
14 |
15 | ```bash
16 | composer require respect/template
17 | ```
18 |
19 | ## License Information
20 |
21 | See [LICENSE](LICENSE) file.
22 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "respect/template",
3 | "description": "Pure HTML templates",
4 | "type": "library",
5 | "homepage": "http://respect.li/",
6 | "license": "BSD Style",
7 | "authors": [
8 | {
9 | "name": "Respect/Template Contributors",
10 | "homepage": "https://github.com/Respect/Template/graphs/contributors"
11 | }
12 | ],
13 | "require": {
14 | "php": ">=5.3.3",
15 | "zendframework/zend-dom": "~2.0"
16 | },
17 | "require-dev": {
18 | "phpunit/phpunit": "~3.0"
19 | },
20 | "autoload": {
21 | "psr-4": {
22 | "Respect\\": "library/Respect/"
23 | }
24 | },
25 | "extra": {
26 | "branch-alias": {
27 | "dev-master": "0.3-dev"
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/examples/001.css:
--------------------------------------------------------------------------------
1 | /* css Zen Garden default style - 'Tranquille' by Dave Shea - http://www.mezzoblue.com/ */
2 | /* css released under Creative Commons License - http://creativecommons.org/licenses/by-nc-sa/1.0/ */
3 | /* All associated graphics copyright 2003, Dave Shea */
4 | /* Added: May 7th, 2003 */
5 |
6 |
7 | /* IMPORTANT */
8 | /* This design is not a template. You may not reproduce it elsewhere without the
9 | designer's written permission. However, feel free to study the CSS and use
10 | techniques you learn from it elsewhere. */
11 |
12 |
13 | /* The Zen Garden default was the first I put together, and almost didn't make the cut. I briefly flirted with using
14 | 'Salmon Cream Cheese' as the main style for the Garden, but switched back to this one before launch.
15 |
16 | All graphics in this design were illustrated by me in Photoshop. Google Image Search provided inspiration for
17 | some of the elements. I did a bit of research on Kanji to come up with the characters on the top left. Anyone who
18 | can read that will most likely tell you it makes no sense, but the best I could do was putting together the
19 | characters for 'beginning' 'complete' and 'skill' to roughly say something like 'we're breaking fresh ground.'
20 |
21 | It's a stretch. */
22 |
23 |
24 | /* basic elements */
25 | html {
26 | margin: 0;
27 | padding: 0;
28 | }
29 | body {
30 | font: 75% georgia, sans-serif;
31 | line-height: 1.88889;
32 | color: #555753;
33 | background: #fff url(/001/blossoms.jpg) no-repeat bottom right;
34 | margin: 0;
35 | padding: 0;
36 | }
37 | p {
38 | margin-top: 0;
39 | text-align: justify;
40 | }
41 | h3 {
42 | font: italic normal 1.4em georgia, sans-serif;
43 | letter-spacing: 1px;
44 | margin-bottom: 0;
45 | color: #7D775C;
46 | }
47 | a:link {
48 | font-weight: bold;
49 | text-decoration: none;
50 | color: #B7A5DF;
51 | }
52 | a:visited {
53 | font-weight: bold;
54 | text-decoration: none;
55 | color: #D4CDDC;
56 | }
57 | a:hover, a:active {
58 | text-decoration: underline;
59 | color: #9685BA;
60 | }
61 | acronym {
62 | border-bottom: none;
63 | }
64 |
65 |
66 | /* specific divs */
67 | #container {
68 | background: url(/001/zen-bg.jpg) no-repeat top left;
69 | padding: 0 175px 0 110px;
70 | margin: 0;
71 | position: relative;
72 | }
73 |
74 | #intro {
75 | min-width: 470px;
76 | width: 100%;
77 | }
78 |
79 | /* using an image to replace text in an h1. This trick courtesy Douglas Bowman, http://www.stopdesign.com/articles/css/replace-text/ */
80 | #pageHeader h1 {
81 | background: transparent url(/001/h1.gif) no-repeat top left;
82 | margin-top: 10px;
83 | display: block;
84 | width: 219px;
85 | height: 87px;
86 | float: left;
87 | }
88 | #pageHeader h1 span {
89 | display:none
90 | }
91 | #pageHeader h2 {
92 | background: transparent url(/001/h2.gif) no-repeat top left;
93 | margin-top: 58px;
94 | margin-bottom: 40px;
95 | width: 200px;
96 | height: 18px;
97 | float: right;
98 | }
99 | #pageHeader h2 span {
100 | display:none
101 | }
102 | #pageHeader {
103 | padding-top: 20px;
104 | height: 87px;
105 | }
106 |
107 | #quickSummary {
108 | clear: both;
109 | margin: 20px 20px 20px 10px;
110 | width: 160px;
111 | float: left;
112 | }
113 | #quickSummary p {
114 | font: italic 1.1em/2.2 georgia;
115 | text-align: center;
116 | }
117 |
118 | #preamble {
119 | clear: right;
120 | padding: 0px 10px 0 10px;
121 | }
122 | #supportingText {
123 | padding-left: 10px;
124 | margin-bottom: 40px;
125 | }
126 |
127 | #footer {
128 | text-align: center;
129 | }
130 | #footer a:link, #footer a:visited {
131 | margin-right: 20px;
132 | }
133 |
134 | #linkList {
135 | margin-left: 600px;
136 | position: absolute;
137 | top: 0;
138 | right: 0;
139 | }
140 | #linkList2 {
141 | font: 10px verdana, sans-serif;
142 | background: transparent url(/001/paper-bg.jpg) top left repeat-y;
143 | padding: 10px;
144 | margin-top: 150px;
145 | width: 130px;
146 | }
147 | #linkList h3.select {
148 | background: transparent url(/001/h3.gif) no-repeat top left;
149 | margin: 10px 0 5px 0;
150 | width: 97px;
151 | height: 16px;
152 | }
153 | #linkList h3.select span {
154 | display:none
155 | }
156 | #linkList h3.favorites {
157 | background: transparent url(/001/h4.gif) no-repeat top left;
158 | margin: 25px 0 5px 0;
159 | width: 60px;
160 | height: 18px;
161 | }
162 | #linkList h3.favorites span {
163 | display:none
164 | }
165 | #linkList h3.archives {
166 | background: transparent url(/001/h5.gif) no-repeat top left;
167 | margin: 25px 0 5px 0;
168 | width:57px;
169 | height: 14px;
170 | }
171 | #linkList h3.archives span {
172 | display:none
173 | }
174 | #linkList h3.resources {
175 | background: transparent url(/001/h6.gif) no-repeat top left;
176 | margin: 25px 0 5px 0;
177 | width:63px;
178 | height: 10px;
179 | }
180 | #linkList h3.resources span {
181 | display:none
182 | }
183 |
184 |
185 | #linkList ul {
186 | margin: 0;
187 | padding: 0;
188 | }
189 | #linkList li {
190 | line-height: 1.3em;
191 | background: transparent url(/001/cr1.gif) no-repeat top center;
192 | display: block;
193 | padding-top: 5px;
194 | margin-bottom: 5px;
195 | list-style-type: none;
196 | }
197 | #linkList li a:link {
198 | color: #988F5E;
199 | }
200 | #linkList li a:visited {
201 | color: #B3AE94;
202 | }
203 |
204 |
205 | #extraDiv1 {
206 | background: transparent url(/001/cr2.gif) top left no-repeat;
207 | position: absolute;
208 | top: 40px;
209 | right: 0;
210 | width: 148px;
211 | height: 110px;
212 | }
213 | .accesskey {
214 | text-decoration: underline;
215 | }
--------------------------------------------------------------------------------
/examples/cssZenGarden.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | css Zen Garden: The Beauty in CSS Design
9 |
10 |
13 |
14 |
15 |
27 |
28 |
29 |
30 |
31 |
32 |
36 |
37 |
38 |
A demonstration of what can be accomplished visually through CSS -based design. Select any style sheet from the list to load it into this page.
39 |
Download the sample html file and css file
40 |
41 |
42 |
43 |
The Road to Enlightenment
44 |
Littering a dark and dreary road lay the past relics of browser-specific tags, incompatible DOM s, and broken CSS support.
45 |
Today, we must clear the mind of past practices. Web enlightenment has been achieved thanks to the tireless efforts of folk like the W3C , WaSP and the major browser creators.
46 |
The css Zen Garden invites you to relax and meditate on the important lessons of the masters. Begin to see with clarity. Learn to use the (yet to be) time-honored techniques in new and invigorating fashion. Become one with the web.
47 |
48 |
49 |
50 |
51 |
52 |
So What is This About?
53 |
There is clearly a need for CSS to be taken seriously by graphic artists. The Zen Garden aims to excite, inspire, and encourage participation. To begin, view some of the existing designs in the list. Clicking on any one will load the style sheet into this very page. The code remains the same, the only thing that has changed is the external .css file. Yes, really.
54 |
CSS allows complete and total control over the style of a hypertext document. The only way this can be illustrated in a way that gets people excited is by demonstrating what it can truly be, once the reins are placed in the hands of those able to create beauty from structure. To date, most examples of neat tricks and hacks have been demonstrated by structurists and coders. Designers have yet to make their mark. This needs to change.
55 |
56 |
57 |
58 |
Participation
59 |
Graphic artists only please. You are modifying this page, so strong CSS skills are necessary, but the example files are commented well enough that even CSS novices can use them as starting points. Please see the CSS Resource Guide for advanced tutorials and tips on working with CSS .
60 |
You may modify the style sheet in any way you wish, but not the HTML . This may seem daunting at first if you’ve never worked this way before, but follow the listed links to learn more, and use the sample files as a guide.
61 |
Download the sample html file and css file to work on a copy locally. Once you have completed your masterpiece (and please, don’t submit half-finished work) upload your .css file to a web server under your control. Send us a link to the file and if we choose to use it, we will spider the associated images. Final submissions will be placed on our server.
62 |
63 |
64 |
65 |
Benefits
66 |
Why participate? For recognition, inspiration, and a resource we can all refer to when making the case for CSS -based design. This is sorely needed, even today. More and more major sites are taking the leap, but not enough have. One day this gallery will be a historical curiosity; that day is not today.
67 |
68 |
69 |
70 |
Requirements
71 |
We would like to see as much CSS1 as possible. CSS2 should be limited to widely-supported elements only. The css Zen Garden is about functional, practical CSS and not the latest bleeding-edge tricks viewable by 2% of the browsing public. The only real requirement we have is that your CSS validates.
72 |
Unfortunately, designing this way highlights the flaws in the various implementations of CSS . Different browsers display differently, even completely valid CSS at times, and this becomes maddening when a fix for one leads to breakage in another. View the Resources page for information on some of the fixes available. Full browser compliance is still sometimes a pipe dream, and we do not expect you to come up with pixel-perfect code across every platform. But do test in as many as you can. If your design doesn’t work in at least IE5+/Win and Mozilla (run by over 90% of the population), chances are we won’t accept it.
73 |
We ask that you submit original artwork. Please respect copyright laws. Please keep objectionable material to a minimum; tasteful nudity is acceptable, outright pornography will be rejected.
74 |
This is a learning exercise as well as a demonstration. You retain full copyright on your graphics (with limited exceptions, see submission guidelines ), but we ask you release your CSS under a Creative Commons license identical to the one on this site so that others may learn from your work.
75 |
Bandwidth graciously donated by mediatemple . Now available: Zen Garden, the book .
76 |
77 |
78 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
Select a Design:
93 |
103 |
104 |
105 |
106 |
Archives:
107 |
111 |
112 |
113 |
114 |
Resources:
115 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/examples/simple.php:
--------------------------------------------------------------------------------
1 | class('p1');
31 | $template['#preamble .p2'] = 'The key concept to understand Respect\Template is simple: isolation of concerns. Backend developers should handle data and serve them properly while frontend developers should do the shinning stuff (CSS and Javascript).';
32 | $template['#preamble .p3'] = 'Respect\Template aims to be easy to use by everyone, with minimum learning curve, minimal impact on the existing code and awesome as possible!';
33 |
34 | echo $template->render();
35 |
--------------------------------------------------------------------------------
/library/Respect/Template/Adapter.php:
--------------------------------------------------------------------------------
1 | adapters[$class] = new $class();
19 | }
20 | }
21 |
22 | public static function getInstance()
23 | {
24 | if (self::$instance instanceof Adapter) {
25 | return self::$instance;
26 | }
27 |
28 | return self::$instance = new Adapter();
29 | }
30 |
31 | public static function factory(DOMDocument $dom, $content)
32 | {
33 | return self::getInstance()->_factory($dom, $content);
34 | }
35 |
36 | public function _factory(DOMDocument $dom, $content)
37 | {
38 | if ($content instanceof AbstractAdapter) {
39 | return $content;
40 | }
41 |
42 | foreach ($this->adapters as $class => $object) {
43 | if ($object->isValidData($content)) {
44 | return new $class($dom, $content);
45 | }
46 | }
47 |
48 | $type = gettype($content);
49 | $type .= (!is_object($type)) ? '' : ' of class '.get_class($content);
50 | throw new UnexpectedValueException('No adapter found for '.$type);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/library/Respect/Template/Adapters/A.php:
--------------------------------------------------------------------------------
1 | hasProperty($data, 'href')) {
13 | return true;
14 | }
15 |
16 | return false;
17 | }
18 |
19 | protected function getDomNode($data, DOMNode $parent)
20 | {
21 | $element = $this->createElement($parent, 'a');
22 | $element->setAttribute('href', $this->getProperty($data, 'href'));
23 | if ($this->hasProperty($data, 'innerHtml')) {
24 | $inner = $this->getProperty($data, 'innerHtml');
25 | $adapter = Adapter::factory($this->getDom(), $inner);
26 | new Append($element, $adapter);
27 | }
28 |
29 | return $element;
30 | }
31 |
32 | public function getDecorator()
33 | {
34 | return 'Respect\Template\Decorators\Replace';
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/library/Respect/Template/Adapters/AbstractAdapter.php:
--------------------------------------------------------------------------------
1 | dom = $dom;
20 | }
21 |
22 | if (!is_null($content)) {
23 | $this->content = $content;
24 | }
25 | }
26 |
27 | abstract public function isValidData($data);
28 | abstract protected function getDomNode($data, DOMNode $parent);
29 |
30 | public function adaptTo(DOMNode $parent, $content = null)
31 | {
32 | $content = ($content) ? $content : $this->content;
33 |
34 | return $this->getDomNode($content, $parent);
35 | }
36 |
37 | protected function createElement(DOMNode $parent, $name, $value = null)
38 | {
39 | if (!$this->dom instanceof DOMDocument) {
40 | throw new UnexpectedValueException('No DOMDocument, cannot create new element');
41 | }
42 |
43 | return $this->dom->createElement($name, $value);
44 | }
45 |
46 | final protected function hasProperty($data, $name)
47 | {
48 | if (is_array($data)) {
49 | return isset($data[$name]);
50 | }
51 |
52 | if (is_object($data)) {
53 | return isset($data->$name);
54 | }
55 |
56 | return false;
57 | }
58 |
59 | public function getDecorator()
60 | {
61 | return 'Respect\Template\Decorators\CleanAppend';
62 | }
63 |
64 | /**
65 | * @return DOMDocument
66 | */
67 | public function getDom()
68 | {
69 | return $this->dom;
70 | }
71 |
72 | final protected function getProperty($data, $name)
73 | {
74 | if (is_array($data)) {
75 | return $data[$name];
76 | }
77 |
78 | if (is_object($data)) {
79 | return $data->$name;
80 | }
81 |
82 | return;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/library/Respect/Template/Adapters/Dom.php:
--------------------------------------------------------------------------------
1 | getDOMNode($this->getDom());
16 | }
17 |
18 | public function getDecorator()
19 | {
20 | return 'Respect\Template\Decorators\Replace';
21 | }
22 | }
23 |
--------------------------------------------------------------------------------
/library/Respect/Template/Adapters/String.php:
--------------------------------------------------------------------------------
1 | hasMethod('__toString');
21 | }
22 |
23 | protected function getDomNode($data, DOMNode $parent)
24 | {
25 | return new DOMText($data);
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/library/Respect/Template/Adapters/Traversable.php:
--------------------------------------------------------------------------------
1 | getChildTag($parent);
16 | $container = $parent->ownerDocument->createDocumentFragment();
17 | foreach ($data as $analyse) {
18 | $value = (is_array($analyse)) ? null : $analyse;
19 | $child = $this->createElement($parent, $tag, $value);
20 | $container->appendChild($child);
21 | if (is_array($analyse)) {
22 | $child->appendChild($this->getDomNode($analyse, $child));
23 | }
24 | }
25 |
26 | return $container;
27 | }
28 |
29 | protected function getChildTag(DOMNode $node)
30 | {
31 | switch ($node->nodeName) {
32 | case 'ol':
33 | case 'ul':
34 | case 'li':
35 | return 'li';
36 | break;
37 | case 'tbody':
38 | case 'table':
39 | case 'thead':
40 | return 'tr';
41 | break;
42 | case 'tr':
43 | return 'td';
44 | break;
45 | default:
46 | return 'span';
47 | break;
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/library/Respect/Template/Decorators/AbstractDecorator.php:
--------------------------------------------------------------------------------
1 | getResult();
20 | }
21 |
22 | if (!is_array($elements)) {
23 | throw new InvalidArgumentException('Query or Array expected to decorate');
24 | }
25 |
26 | // Decorate the given elements selected
27 | foreach ($elements as $element) {
28 | if (!$element instanceof DOMNode) {
29 | throw new UnexpectedValueException('DOMNode expected for decoration');
30 | }
31 |
32 | if (!is_null($with)) {
33 | $with = $with->adaptTo($element);
34 | }
35 | $this->decorate($element, $with);
36 | }
37 | }
38 |
39 | abstract protected function decorate(DOMNode $node, DOMNode $with = null);
40 | }
41 |
--------------------------------------------------------------------------------
/library/Respect/Template/Decorators/Append.php:
--------------------------------------------------------------------------------
1 | appendChild($with);
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/library/Respect/Template/Decorators/Clean.php:
--------------------------------------------------------------------------------
1 | childNodes as $child) {
12 | $remove[] = $child;
13 | }
14 |
15 | foreach ($remove as $child) {
16 | $node->removeChild($child);
17 | }
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/library/Respect/Template/Decorators/CleanAppend.php:
--------------------------------------------------------------------------------
1 | appendChild($with);
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/library/Respect/Template/Decorators/Replace.php:
--------------------------------------------------------------------------------
1 | ownerDocument->importNode($with, true);
13 | $return = $old->parentNode->replaceChild($new, $old);
14 | if ($return !== $old) {
15 | throw new UnexpectedValueException('Unable to replace node');
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/library/Respect/Template/Document.php:
--------------------------------------------------------------------------------
1 |
14 | */
15 | class Document
16 | {
17 | /**#@+
18 | * Constants to define the docnype of the document.
19 | *
20 | * @link http://www.w3.org/QA/2002/04/valid-dtd-list.html
21 | * @author Nick Lombard
22 | */
23 | const HTML_5 = <<<'HTML'
24 |
25 | HTML;
26 | const HTML_4_01_STRICT = <<<'EOD'
27 |
29 | EOD;
30 | const HTML_4_01_TRANSITIONAL = <<<'EOD'
31 |
33 | EOD;
34 | const HTML_4_01_FRAMESET = <<<'EOD'
35 |
37 | EOD;
38 | const XHTML_1_0_STRICT = <<<'EOD'
39 |
41 | EOD;
42 | const XHTML_1_0_TRANSITIONAL = <<<'EOD'
43 |
45 | EOD;
46 | const XHTML_1_0_FRAMESET = <<<'EOD'
47 |
49 | EOD;
50 | const XHTML_1_1 = <<<'EOD'
51 |
53 | EOD;
54 | const XHTML_1_1_BASIC = <<<'EOD'
55 |
57 | EOD;
58 | const MATHML_2_0 = <<<'EOD'
59 |
61 | EOD;
62 | const MATHML_1_01 = <<<'EOD'
63 |
65 | EOD;
66 | const XHTML_MATHML_SVG = <<<'EOD'
67 |
70 | EOD;
71 | const XHTML_MATHML_SVG_PROFILE_XHTML = <<<'EOD'
72 |
75 | EOD;
76 | const XHTML_MATHML_SVG_PROFILE_SVG = <<<'EOD'
77 |
80 | EOD;
81 | const SVG_1_1 = <<<'EOD'
82 |
84 | EOD;
85 | const SVG_1_0 = <<<'EOD'
86 |
88 | EOD;
89 | const SVG_1_1_BASIC = <<<'EOD'
90 |
92 | EOD;
93 | const SVG_1_1_TINY = <<<'EOD'
94 |
96 | EOD;
97 | const HTML_2_0 = <<<'EOD'
98 |
99 | EOD;
100 | const HTML_3_2 = <<<'EOD'
101 |
102 | EOD;
103 | const XHTML_1_0_BASIC = <<<'EOD'
104 |
106 | EOD;
107 | /**#@-*/
108 |
109 | /**
110 | * @var DOMDocument
111 | */
112 | private $dom;
113 | /**
114 | * @var Zend_Dom_Query
115 | */
116 | private $queryDocument;
117 |
118 | /**
119 | * @param string $htmlDocument
120 | */
121 | public function __construct($htmlDocument)
122 | {
123 | $this->dom = new DOMDocument();
124 | $this->dom->strictErrorChecking = false;
125 | $this->dom->loadHtml($htmlDocument);
126 | }
127 |
128 | /**
129 | * @return DOMDocument
130 | */
131 | public function getDom()
132 | {
133 | return $this->dom;
134 | }
135 |
136 | /**
137 | * Replaces this dom content with the given array.
138 | * The array structure is: $array['Css Selector to Eelement'] = 'content';
139 | *
140 | * @param array $data
141 | * @param string[optional] $decorator Class to be used as decorator
142 | * @return Respect\Template\Document
143 | */
144 | public function decorate(array $data, $decorator = null)
145 | {
146 | foreach ($data as $selector => $with) {
147 | $adapter = Adapter::factory($this->getDom(), $with);
148 | $decorator = $decorator ?: $adapter->getDecorator();
149 | $query = new Query($this, $selector);
150 | new $decorator($query, $adapter);
151 | }
152 |
153 | return $this;
154 | }
155 |
156 | /**
157 | * Returns the XML representation of the current DOM tree.
158 | *
159 | * @param boolean $beautiful - to pretty print or not
160 | * @param string $doctype - the doctype to use
161 | * @return string
162 | */
163 | public function render($beautiful = false, $doctype = '')
164 | {
165 | $this->dom->formatOutput = $beautiful;
166 |
167 | if ($doctype) {
168 | $doc = new DOMDocument();
169 | $doc->loadHTML($doctype);
170 | $dt = $doc->doctype;
171 | $di = new DOMImplementation();
172 | $dt = $di->createDocumentType($dt->name, $dt->publicId, $dt->systemId);
173 | $this->dom->replaceChild($dt, $this->dom->doctype);
174 | }
175 |
176 | return preg_replace('/<\?xml[\s\S]*\?>\n/', '', $this->dom->saveXML());
177 | }
178 |
179 | /**
180 | * Returns XML to be parsed by CSS the selector.
181 | * This will never be the final XML to be rendered.
182 | *
183 | * @return string
184 | */
185 | public function getQueryDocument()
186 | {
187 | if (! $this->queryDocument) {
188 | return $this->queryDocument = new DomQuery($this->render());
189 | }
190 |
191 | return $this->queryDocument;
192 | }
193 | }
194 |
--------------------------------------------------------------------------------
/library/Respect/Template/Html.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | const HTML_5 = Document::HTML_5;
15 | const HTML_4_01_STRICT = Document::HTML_4_01_STRICT;
16 | const HTML_4_01_TRANSITIONAL = Document::HTML_4_01_TRANSITIONAL;
17 | const HTML_4_01_FRAMESET = Document::HTML_4_01_FRAMESET;
18 | const XHTML_1_0_STRICT = Document::XHTML_1_0_STRICT;
19 | const XHTML_1_0_TRANSITIONAL = Document::XHTML_1_0_TRANSITIONAL;
20 | const XHTML_1_0_FRAMESET = Document::XHTML_1_0_FRAMESET;
21 | const XHTML_1_1 = Document::XHTML_1_1;
22 | const XHTML_1_1_BASIC = Document::XHTML_1_1_BASIC;
23 | const HTML_2_0 = Document::HTML_2_0;
24 | const HTML_3_2 = Document::HTML_3_2;
25 | const XHTML_1_0_BASIC = Document::XHTML_1_0_BASIC;
26 | /**#@-*/
27 |
28 | /**
29 | * @var Respect\Template\Document
30 | */
31 | protected $document;
32 | public $aliasFor = array();
33 |
34 | public function __construct($templateFileOrString)
35 | {
36 | if (file_exists($templateFileOrString)) {
37 | $content = file_get_contents($templateFileOrString);
38 | } else {
39 | $content = $templateFileOrString;
40 | }
41 | $this->document = new Document($content);
42 | }
43 |
44 | public function __toString()
45 | {
46 | return $this->render();
47 | }
48 |
49 | public function inheritFrom(Html $model, $blockSelector, $anotherSelector = null, $etc = null)
50 | {
51 | $selectors = array_slice(func_get_args(), 1);
52 | foreach ($selectors as $selector) {
53 | foreach ($model->find($selector) as $modelNode) {
54 | foreach ($this->find($selector) as $targetNode) {
55 | $targetNode->parentNode->replaceChild(
56 | $this->document->getDom()->importNode($modelNode, true),
57 | $targetNode
58 | );
59 | }
60 | }
61 | }
62 | }
63 |
64 | public function getDocument()
65 | {
66 | return $this->document;
67 | }
68 |
69 | /**
70 | * @return array
71 | */
72 | public function find($selector)
73 | {
74 | $query = new Query($this->document, $selector);
75 |
76 | return $query->getResult();
77 | }
78 |
79 | /**
80 | * Returns the HTML document.
81 | *
82 | * @param array $data - The data to render
83 | * @param boolean $beatiful - To pretty print or not
84 | * @param string $doctype - The doctype of this html
85 | * @return string
86 | */
87 | public function render($data = null, $beatiful = false, $doctype = '')
88 | {
89 | foreach ($this->aliasFor as $selector => $alias) {
90 | $this[$selector] = $this[$alias];
91 | }
92 |
93 | $data = $data ?: $this->getArrayCopy();
94 |
95 | return $this->document->decorate($data)->render($beatiful, $doctype);
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/library/Respect/Template/HtmlElement.php:
--------------------------------------------------------------------------------
1 | nodeName = $name;
16 | $this->childrenNodes = $children;
17 | }
18 |
19 | public function __call($attribute, $value)
20 | {
21 | $attribute = strtolower(preg_replace('/[A-Z]/', '-$0', $attribute));
22 | $this->attributes[$attribute] = $value[0];
23 |
24 | return $this;
25 | }
26 |
27 | public static function __callStatic($name, array $children)
28 | {
29 | return new static($name, $children);
30 | }
31 |
32 | public function __toString()
33 | {
34 | $children = implode($this->childrenNodes);
35 | $attrs = '';
36 | foreach ($this->attributes as $attr => &$value) {
37 | $attrs .= " $attr=\"$value\"";
38 | }
39 |
40 | if (count($this->childrenNodes)) {
41 | return "<{$this->nodeName}{$attrs}>$children{$this->nodeName}>";
42 | }
43 |
44 | return "<{$this->nodeName}{$attrs} />";
45 | }
46 |
47 | public function getDOMNode(DOMDocument $dom = null, $current = null)
48 | {
49 | if (is_null($dom)) {
50 | $dom = new DOMDocument();
51 | }
52 |
53 | if (is_string($current)) {
54 | return new DOMText($current);
55 | }
56 |
57 | $current = $current ?: $this;
58 | $node = $dom->createElement($current->nodeName);
59 | foreach ($current->attributes as $name => $value) {
60 | $node->setAttribute($name, $value);
61 | }
62 |
63 | if (!count($current->childrenNodes)) {
64 | return $node;
65 | }
66 |
67 | foreach ($current->childrenNodes as $child) {
68 | $node->appendChild($this->getDOMNode($dom, $child));
69 | }
70 |
71 | return $node;
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/library/Respect/Template/Query.php:
--------------------------------------------------------------------------------
1 | document = $doc;
26 | $this->selector = $selector;
27 | }
28 |
29 | /**
30 | * @return array
31 | */
32 | public function getResult()
33 | {
34 | // Get results by a CSS selector
35 | $selector = $this->selector;
36 | $document = $this->document->getQueryDocument();
37 | $results = $document->execute($selector);
38 | $xpath = $results->getXpathQuery();
39 | $domxpath = new DOMXPath($this->document->getDom());
40 | $nodelist = iterator_to_array($domxpath->query($xpath));
41 |
42 | return $nodelist;
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
11 |
12 |
13 | tests
14 |
15 |
16 |
17 |
18 | library/
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/tests/library/Respect/Template/AdapterTest.php:
--------------------------------------------------------------------------------
1 | dom = new DOMDocument('1.0', 'iso-8859-1');
15 | }
16 | public function testFactoryException()
17 | {
18 | $this->setExpectedException('UnexpectedValueException');
19 | Adapter::factory($this->dom, new Pdo('sqlite::memory:'));
20 | }
21 |
22 |
23 | public function instances()
24 | {
25 | $anchorObject = new StdClass();
26 | $anchorObject->href = 'test';
27 | return array(
28 | array('A', array('href'=>'test'), 'Replace'),
29 | array('A', $anchorObject, 'Replace'),
30 | array('Dom', new DOMText, 'CleanAppend'),
31 | array('String', 'Hello World!', 'CleanAppend'),
32 | array('Traversable', array('one', 'two', 'three', 'pigs'), 'CleanAppend'),
33 | array('HtmlElement', H::ul(H::li('one')), 'Replace')
34 | );
35 | }
36 | /**
37 | * @dataProvider instances
38 | */
39 | public function testInstances($className, $content, $decorator)
40 | {
41 | $adapter = Adapter::factory($this->dom, $content);
42 | $className = 'Respect\Template\Adapters\\'.$className;
43 | $decorator = 'Respect\Template\Decorators\\'.$decorator;
44 | $this->assertInstanceOf($className, $adapter);
45 | $this->assertEquals($decorator, $adapter->getDecorator());
46 |
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/tests/library/Respect/Template/Adapters/ATest.php:
--------------------------------------------------------------------------------
1 | dom = new DOMDocument('1.0', 'iso-8859-1');
16 | }
17 |
18 | public function testReplaceDecorator()
19 | {
20 | $object = new Adapter();
21 | $class = $object->getDecorator();
22 | $this->assertEquals('Respect\Template\Decorators\Replace', $class);
23 | }
24 |
25 | public function testSimpleAdaptation()
26 | {
27 | $href = '#top';
28 | $from = array('href'=>$href);
29 | $adapter = A::factory($this->dom, $from);
30 | $this->assertInstanceOf('Respect\Template\Adapters\A', $adapter);
31 | $to = $adapter->adaptTo($this->dom);
32 | $this->assertInstanceOf('DOMElement', $to);
33 | $this->assertTrue($to->hasAttribute('href'));
34 | $this->assertEquals($href, $to->getAttribute('href'));
35 | }
36 |
37 | public function testAdaptationWithInnerHtml()
38 | {
39 | $std = new StdClass();
40 | $std->href = '#top';
41 | $std->innerHtml = 'Top';
42 | $adapter = A::factory($this->dom, $std);
43 | $this->assertInstanceOf('Respect\Template\Adapters\A', $adapter);
44 | $to = $adapter->adaptTo($this->dom);
45 | $this->assertInstanceOf('DOMElement', $to);
46 | $this->assertTrue($to->hasAttribute('href'));
47 |
48 | $expected = $this->dom->createElement('a', 'Top');
49 | $expected->setAttribute('href', '#top');
50 | $this->assertEquals($expected, $to);
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/tests/library/Respect/Template/Adapters/HtmlElementTest.php:
--------------------------------------------------------------------------------
1 | dom = new DOMDocument('1.0', 'iso-8859-1');
14 | }
15 |
16 | public function testInstance()
17 | {
18 | $expected = 'Respect\Template\Adapters\AbstractAdapter';
19 | $this->assertInstanceOf($expected, new Adapter());
20 | }
21 |
22 | public function testFactory()
23 | {
24 | $test = Factory::factory($this->dom, H::ul());
25 | $expected = 'Respect\Template\Adapters\HtmlElement';
26 | $this->assertInstanceOf($expected, $test);
27 | }
28 |
29 | public function testDecorator()
30 | {
31 | $expected = 'Respect\Template\Decorators\Replace';
32 | $adapter = new Adapter();
33 | $this->assertEquals($expected, $adapter->getDecorator());
34 | }
35 |
36 | public function testAdaptation()
37 | {
38 | $parent = $this->dom->createElement('div');
39 | $expected = $this->dom->createElement('ul');
40 | $base = H::ul();
41 | $adapter = Factory::factory($this->dom, $base);
42 | $this->assertInstanceOf('Respect\Template\Adapters\HtmlElement', $adapter);
43 | $this->assertEquals($expected, $adapter->adaptTo($parent));
44 | }
45 | }
--------------------------------------------------------------------------------
/tests/library/Respect/Template/Adapters/StringTest.php:
--------------------------------------------------------------------------------
1 | dom = new DOMDocument('1.0', 'iso-8859-1');
11 | }
12 |
13 | public function testInstance()
14 | {
15 | $this->assertInstanceOf('Respect\Template\Adapters\AbstractAdapter', new String());
16 | }
17 |
18 | public function testSimpleAdaptation()
19 | {
20 | $div = $this->dom->createElement('div');
21 | $div->setAttribute('id', 'test');
22 | $this->dom->appendChild($div);
23 |
24 | $string = 'This is a simple string';
25 | $adapter = new String($this->dom);
26 | $this->assertTrue($adapter->isValidData($string));
27 | $adapted = $adapter->adaptTo($div, $string);
28 | $div->appendChild($adapted);
29 | $this->assertInstanceOf('DOMText', $adapted);
30 | $this->assertContains('This is a simple string
', $this->dom->saveXml());
31 | }
32 | }
--------------------------------------------------------------------------------
/tests/library/Respect/Template/Adapters/TraversableTest.php:
--------------------------------------------------------------------------------
1 | dom = new DOMDocument('1.0', 'iso-8859-1');
10 | }
11 |
12 | protected function assertContainTraversables($traversables)
13 | {
14 | $xml = $this->dom->saveXml();
15 | foreach ($traversables as $item) {
16 | if (is_string($item))
17 | $this->assertContains($item, $xml, "'{$item}' not found in: ".$xml);
18 | if (is_array($item))
19 | $this->assertContainTraversables($item);
20 | }
21 | }
22 |
23 | public function testInstance()
24 | {
25 | $this->assertInstanceOf('Respect\Template\Adapters\AbstractAdapter', new Traversable());
26 | }
27 |
28 | public function testSimpleAdaptation()
29 | {
30 | $ul = $this->dom->createElement('ul');
31 | $ul->setAttribute('id', 'test');
32 | $this->dom->appendChild($ul);
33 |
34 | $array = array('one', 'two', 'three');
35 | $adapter = new Traversable($this->dom);
36 | $this->assertTrue($adapter->isValidData($array));
37 | $adapted = $adapter->adaptTo($ul, $array);
38 | $ul->appendChild($adapted);
39 | $this->assertInstanceOf('DOMDocumentFragment', $adapted);
40 |
41 | $xml = $this->dom->saveXml();
42 | $this->assertContains('one ', $xml);
43 | $this->assertContains('two ', $xml);
44 | $this->assertContains('three ', $xml);
45 | $this->assertContains('', $xml);
46 | }
47 |
48 | public function strings()
49 | {
50 | // Elements: tag, injector, final string
51 | return array(
52 | array('ul', array('one', 'two'), 'one two '),
53 | array('table', array(array('1', '2')), '1 2 '),
54 | array('h1', array('hi'), 'hi ')
55 | );
56 | }
57 |
58 |
59 | /**
60 | * @dataProvider strings
61 | */
62 | public function testMultipleAdaptations($tag, $injector, $finalString)
63 | {
64 | $node = $this->dom->createElement($tag);
65 | $this->dom->appendChild($node);
66 |
67 | $this->assertFalse($node->hasChildNodes());
68 | $adapter = new Traversable($this->dom);
69 | $node->appendChild($adapter->adaptTo($node, $injector));
70 | $this->assertTrue($node->hasChildNodes());
71 | $this->assertContains($finalString, $this->dom->saveXml());
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/tests/library/Respect/Template/Decorators/AppendTest.php:
--------------------------------------------------------------------------------
1 | createElement('div');
22 | $expect = ''.$with.'
';
23 | $elements = array($node);
24 | $doc->appendChild($node);
25 |
26 | $this->assertFalse($node->hasChildNodes());
27 | new Append($elements, Adapter::factory($doc, $with));
28 | $this->assertTrue($node->hasChildNodes());
29 | $this->assertContains($expect, $doc->saveXml());
30 | }
31 | }
--------------------------------------------------------------------------------
/tests/library/Respect/Template/Decorators/CleanAppendTest.php:
--------------------------------------------------------------------------------
1 | dom = new DOMDocument('1.0', 'iso-8859-1');
13 | }
14 |
15 | public function traversables()
16 | {
17 | return array(
18 | array(array('one', 'two', 'three')),
19 | );
20 | }
21 |
22 | /**
23 | * @dataProvider traversables
24 | */
25 | public function testInjectingOnAUl($with)
26 | {
27 | $ul = $this->dom->createElement('ul');
28 | for ($i=3; $i>0; $i--)
29 | $ul->appendChild($this->dom->createElement('li', 'test'));
30 | $this->dom->appendChild($ul);
31 |
32 |
33 | $this->assertTrue($ul->hasChildNodes());
34 | new Decorator(array($ul), Adapter::factory($this->dom, $with));
35 | $this->assertTrue($ul->hasChildNodes());
36 | }
37 | }
--------------------------------------------------------------------------------
/tests/library/Respect/Template/Decorators/CleanTest.php:
--------------------------------------------------------------------------------
1 | dom = new DOMDocument('1.0', 'iso-8859-1');
12 | }
13 |
14 | public function testSingleChild()
15 | {
16 | $ul = $this->dom->createElement('ul');
17 | $li = $this->dom->createElement('li');
18 | $ul->appendChild($li);
19 |
20 | $this->assertEquals(1, $ul->childNodes->length);
21 | new Clean(array($ul));
22 | $this->assertEquals(0, $ul->childNodes->length);
23 | }
24 |
25 | /**
26 | * @depends testSingleChild
27 | */
28 | public function testMultipleChildren()
29 | {
30 | $ul = $this->dom->createElement('ul');
31 | $expect = 5;
32 | for ($i=0; $i<$expect; $i++)
33 | $ul->appendChild($this->dom->createElement('li'));
34 |
35 | $this->assertEquals($expect, $ul->childNodes->length);
36 | new Clean(array($ul));
37 | $this->assertEquals(0, $ul->childNodes->length, $ul->childNodes);
38 | }
39 |
40 | }
--------------------------------------------------------------------------------
/tests/library/Respect/Template/Decorators/ReplaceTest.php:
--------------------------------------------------------------------------------
1 | dom = new DOMDocument('1.0', 'iso-8859-1');
16 | }
17 |
18 | public function testSimpleReplace()
19 | {
20 | $div = $this->dom->createElement('div', 'it does not matter');
21 | $span = $this->dom->createElement('span', 'it matters');
22 | $this->dom->appendChild($div);
23 | new Decorator($div, Adapter::factory($this->dom, $span));
24 | $this->assertContains('it matters ', $this->dom->saveXML());
25 | }
26 | }
--------------------------------------------------------------------------------
/tests/library/Respect/Template/HtmlElementTest.php:
--------------------------------------------------------------------------------
1 | assertEquals('
', (string) $empty);
15 | }
16 |
17 | public function testAttributesOnlyElement()
18 | {
19 | $input = H::input()->type('text')->id('test');
20 | $this->assertEquals(' ', (string) $input);
21 | }
22 |
23 | public function testUnCamelAttributes()
24 | {
25 | $div = H::div('Uhull')->dataToggle('test');
26 | $this->assertEquals('Uhull
', (string) $div);
27 | }
28 |
29 | public function testAttributesAndChildren()
30 | {
31 | $div = H::div('Uhull')->id('test');
32 | $this->assertEquals('Uhull
', (string) $div);
33 | }
34 |
35 | public function testChildrenAsHtmlElement()
36 | {
37 | $ul = H::ul(
38 | H::li('one'),
39 | H::li('two')
40 | );
41 | $this->assertEquals('', (string) $ul);
42 | }
43 |
44 | public function testGetDomNode()
45 | {
46 | $dom = new DOMDocument('1.0', 'iso-8859-1');
47 | $ul = $dom->createElement('ul');
48 | $ul->appendChild($dom->createElement('li', 'one'));
49 | $ul->appendChild($dom->createElement('li', 'two'));
50 | $this->assertEquals(
51 | $ul,
52 | H::ul(H::li('one'), H::li('two'))->getDomNode()
53 | );
54 | }
55 | }
56 |
57 |
--------------------------------------------------------------------------------
/tests/library/Respect/Template/HtmlTest.php:
--------------------------------------------------------------------------------
1 | _ ', array('#test'=>'Hi'), ''),
10 | array('', array('#test'=>array('A','B')), '')
11 | );
12 | }
13 |
14 | /**
15 | * @dataProvider constructs
16 | */
17 | public function testSetTemplate($template, $data, $expected)
18 | {
19 | $view = new Html($template);
20 | $out = $view->render();
21 | $this->assertContains($template, $out, "Output does not have the defined template: {$out}");
22 | }
23 |
24 | /**
25 | * @depends testSetTemplate
26 | * @dataProvider constructs
27 | */
28 | public function testPassingDataToRender($template, $data, $expected)
29 | {
30 | $view = new Html($template);
31 | $result = $view->render($data);
32 | $this->assertContains($expected, $result);
33 | }
34 |
35 | /**
36 | * @depends testPassingDataToRender
37 | * @dataProvider constructs
38 | */
39 | public function testTemplateWithArrayObject($template, $data, $expected)
40 | {
41 | $view = new Html($template);
42 | foreach ($data as $key=>$val)
43 | $view[$key] = $val;
44 |
45 | $this->assertEquals($data, $view->getArrayCopy(), 'ArrayObject did not work to set data for template');
46 | $this->assertContains($expected, (string) $view);
47 | }
48 |
49 | public function testArrayAccessInterface()
50 | {
51 | $template = new Html('
');
52 | $this->assertInstanceOf('ArrayAccess', $template);
53 | $this->assertFalse(isset($template['one']));
54 | $template['one'] = 'one';
55 | $this->assertTrue(isset($template['one']));
56 | $this->assertEquals('one', $template['one']);
57 | unset($template['one']);
58 | $this->assertFalse(isset($template['one']));
59 | }
60 |
61 | public function testResolveAliases()
62 | {
63 | $v = new Html("\n \n");
64 | $v->aliasFor["h1 > span"] = "pagetitle";
65 | $v["pagetitle"] = "FooBar";
66 | $this->assertEquals("\nFooBar \n", (string) $v);
67 | }
68 |
69 | public function testSimpleInheritance()
70 | {
71 | $template = new Html("\nMy Text
\n");
72 | $model = new Html("\n");
73 | $template->inheritFrom($model, "h1");
74 | $this->assertEquals("\nMy Text
\n", (string) $template);
75 | }
76 | }
77 |
--------------------------------------------------------------------------------